SQL qaytariladigan satrlarni takrorlash

Veb-saytimdagi barcha asosiy postlarni ko'rsatish uchun juda zarur bo'lgan asosiy tizimni ishlab chiqyapman:

  1. Yozuvlar kirishdagi foydalanuvchidan emas.
  2. Hammalari do'stlaridan.
  3. va post_id tomonidan buyurtma qilinadi (birinchi bo'lib eng so'nggilari olish uchun)

SQL bilan bo'lgan bir muammo, satrlarni yopish uchun ma'lumotlar bazasini jadvali ga so'rov yuborganda, u bitta xabarni qaytaradi, lekin u < strong> barcha foydalanuvchilarni yaratdi.

Masalan, agar 1 foydalanuvchi "Salom" holatini yozgan bo'lsa va ma'lumotlar bazasida 5 foydalanuvchi mavjud bo'lsa; u postni egallaydi, keyin uni har bir individual foydalanuvchi bilan birga afishada sifatida 5 marta chop eting. (Misol uchun namunaga qarang)

SQL:

SELECT posts.*, users.*, friends.* 
FROM posts, users, friends
WHERE posts.poster <> ? 
AND users.user_id = posts.poster
AND friends.areFriends = 1 AND (friends.userA = ? AND friends.userB = posts.poster) 
OR friends.areFriends = 1 AND (friends.userA = posts.poster AND friends.userB = ?)
ORDER BY posts.post_id desc LIMIT 20

Malumot uchun:

posts.poster is the person who created the post
users.user_id is the id of the same person friends.areFriends 0 = not a friend, 1 = friend friends.userA/friends.userB is the logged in user or the friend that that user is friends with (if that makes sense)

Bug Image

Muammoni bartaraf etish uchun biladigan har qanday kombinatsiyani sinab ko'rdim, biroq men hali "rivojlangan" uchun SQL va yangi narsa topolmayapman

Muammoni eng yaxshi deb tushuntirishga harakat qildim, shuning uchun kimdir menga yordam berishi mumkin. Men oxirgi ikki kun davomida uni tuzatish uchun harakat qilyapman, lekin hech qanday foyda yo'q,

Cheers.

2
@Jibin bu javobni do'stim deb yozishi kerak! : D
qo'shib qo'ydi muallif GROVER., manba
@Jibin bu javobni do'stim deb yozishi kerak! : D
qo'shib qo'ydi muallif GROVER., manba
@Jibin bu javobni do'stim deb yozishi kerak! : D
qo'shib qo'ydi muallif GROVER., manba
Yaqin ovoz berish uchun ovoz bergan shaxsga; iltimos, sizning savollaringiz uchun sizni qisqartirishim uchun qanday qilib yaxshilashim mumkinligini tushuntirib bering :) Men buni imkon qadar aniq qilib ayta olgandek his qilaman, ammo takliflar uchun ochiqman!
qo'shib qo'ydi muallif GROVER., manba
Yaqin ovoz berish uchun ovoz bergan shaxsga; iltimos, sizning savollaringiz uchun sizni qisqartirishim uchun qanday qilib yaxshilashim mumkinligini tushuntirib bering :) Men buni imkon qadar aniq qilib ayta olgandek his qilaman, ammo takliflar uchun ochiqman!
qo'shib qo'ydi muallif GROVER., manba
@AmanKumar juda n00b haha ​​uchun juda sirli
qo'shib qo'ydi muallif GROVER., manba
@AmanKumar juda n00b haha ​​uchun juda sirli
qo'shib qo'ydi muallif GROVER., manba
SQL JOINS dan foydalaning ...
qo'shib qo'ydi muallif Aman Kumar, manba
SQL JOINS dan foydalaning ...
qo'shib qo'ydi muallif Aman Kumar, manba
@GROVER Ok.Am
qo'shib qo'ydi muallif Jibin, manba
@GROVER Ok.Am
qo'shib qo'ydi muallif Jibin, manba
@GROVER Ok.Am
qo'shib qo'ydi muallif Jibin, manba

7 javoblar

where shartlari tufayli bo'lishi kerak. Buni quyidagicha o'zgartiring:

WHERE posts.poster <> ? 
AND users.user_id = posts.poster
AND friends.areFriends = 1 
AND ((friends.userA = ? AND friends.userB = posts.poster) OR (friends.userA = posts.poster AND friends.userB = ?))

Shartlarni yozganingizda, u boshqa barcha shartlarni bajaradigan satrlarni qaytaradi yoki friends.areFriends = 1 AND (friends.userA = posts.poster AND friends.userB =?) . Shuning uchun users.user_id = posts.poster ni bajarib bo'lmaydigan satr qaytariladi. Lekin shartlarni yozganimday, YoKI Qavslar ichiga olingan.

2
qo'shib qo'ydi
Faqat kod bo'lgan javoblar va nima uchun tuzilgan/takomillashtirilganligini tushuntirmaysan, bu foydali emas, Said.
qo'shib qo'ydi muallif Martin, manba
Rahmat, men buni sinab ko'raman! Qanday qilib bu ishlayotganini va qanday qilib bu menikidan farq qilishini aytmoqchi? :) Men kelajakda undan saboq olishim mumkin
qo'shib qo'ydi muallif GROVER., manba
Mening javobim yaxshilandi
qo'shib qo'ydi muallif Saeed, manba
Bu users.user_id = posts.poster sharti bilan amalga oshirish o'rniga, bu JOIN yordamida bu muammolarni bartaraf qiladi, lekin bu bilan ham shunday qilish mumkin
qo'shib qo'ydi muallif Saeed, manba
Said, takrorlash jadvallarni bir-biriga to'g'ri kelmasligi kerak. Bu juda keng tarqalgan xato.
qo'shib qo'ydi muallif Robert Baron, manba

where shartlari tufayli bo'lishi kerak. Buni quyidagicha o'zgartiring:

WHERE posts.poster <> ? 
AND users.user_id = posts.poster
AND friends.areFriends = 1 
AND ((friends.userA = ? AND friends.userB = posts.poster) OR (friends.userA = posts.poster AND friends.userB = ?))

Shartlarni yozganingizda, u boshqa barcha shartlarni bajaradigan satrlarni qaytaradi yoki friends.areFriends = 1 AND (friends.userA = posts.poster AND friends.userB =?) . Shuning uchun users.user_id = posts.poster ni bajarib bo'lmaydigan satr qaytariladi. Lekin shartlarni yozganimday, YoKI Qavslar ichiga olingan.

2
qo'shib qo'ydi
Faqat kod bo'lgan javoblar va nima uchun tuzilgan/takomillashtirilganligini tushuntirmaysan, bu foydali emas, Said.
qo'shib qo'ydi muallif Martin, manba
Rahmat, men buni sinab ko'raman! Qanday qilib bu ishlayotganini va qanday qilib bu menikidan farq qilishini aytmoqchi? :) Men kelajakda undan saboq olishim mumkin
qo'shib qo'ydi muallif GROVER., manba
Bu users.user_id = posts.poster sharti bilan amalga oshirish o'rniga, bu JOIN yordamida bu muammolarni bartaraf qiladi, lekin bu bilan ham shunday qilish mumkin
qo'shib qo'ydi muallif Saeed, manba
Mening javobim yaxshilandi
qo'shib qo'ydi muallif Saeed, manba
Said, takrorlash jadvallarni bir-biriga to'g'ri kelmasligi kerak. Bu juda keng tarqalgan xato.
qo'shib qo'ydi muallif Robert Baron, manba

where shartlari tufayli bo'lishi kerak. Buni quyidagicha o'zgartiring:

WHERE posts.poster <> ? 
AND users.user_id = posts.poster
AND friends.areFriends = 1 
AND ((friends.userA = ? AND friends.userB = posts.poster) OR (friends.userA = posts.poster AND friends.userB = ?))

Shartlarni yozganingizda, u boshqa barcha shartlarni bajaradigan satrlarni qaytaradi yoki friends.areFriends = 1 AND (friends.userA = posts.poster AND friends.userB =?) . Shuning uchun users.user_id = posts.poster ni bajarib bo'lmaydigan satr qaytariladi. Lekin shartlarni yozganimday, YoKI Qavslar ichiga olingan.

2
qo'shib qo'ydi
Faqat kod bo'lgan javoblar va nima uchun tuzilgan/takomillashtirilganligini tushuntirmaysan, bu foydali emas, Said.
qo'shib qo'ydi muallif Martin, manba
Rahmat, men buni sinab ko'raman! Qanday qilib bu ishlayotganini va qanday qilib bu menikidan farq qilishini aytmoqchi? :) Men kelajakda undan saboq olishim mumkin
qo'shib qo'ydi muallif GROVER., manba
Mening javobim yaxshilandi
qo'shib qo'ydi muallif Saeed, manba
Bu users.user_id = posts.poster sharti bilan amalga oshirish o'rniga, bu JOIN yordamida bu muammolarni bartaraf qiladi, lekin bu bilan ham shunday qilish mumkin
qo'shib qo'ydi muallif Saeed, manba
Said, takrorlash jadvallarni bir-biriga to'g'ri kelmasligi kerak. Bu juda keng tarqalgan xato.
qo'shib qo'ydi muallif Robert Baron, manba

Ichki qo'shilishlarni yaratishning klassik usuli, ko'proq o'qilishi mumkin va kod nima uchun ishlashini tushunishga yordam beradi. Bundan tashqari, bu SQL uchun kod konversiyasidir, shuning uchun ham sizni (men kabi) sizni tushunishga yordam beradi.

Kodni INNER JOIN dan foydalanish uchun qayta yozdim. Buni sinab ko'ring.

SELECT @userId := ?;

SELECT posts.*, users.*, friends.* 
FROM friends
JOIN users ON users.user_id = 
    CASE friends.userA
    WHEN @userId
    THEN friends.userB
    ELSE friends.userA END
JOIN posts ON posts.poster = users.user_id
WHERE friends.userA = @userId OR friends.userB = @userId
ORDER BY posts.post_id DESC LIMIT 20;

friends jadvali ichida dublar yo'qligiga ishonch hosil qiling. Quyidagi so'rovlar sizga yordam beradi:

SELECT User1, User2, COUNT(*) as DupeCount
FROM 
(
    SELECT
        CASE WHEN friends.userA < friends.userB THEN friends.userA ELSE friends.userB END AS User1,
        CASE WHEN friends.userA < friends.userB THEN friends.userB ELSE friends.userA END AS User2
    FROM friends
) AS F
GROUP BY User1, User2
HAVING COUNT(*) > 1
2
qo'shib qo'ydi
Rahmat, men buni sinab ko'raman! :) Nima uchun men userIdni INT deb e'lon qilishim kerak?
qo'shib qo'ydi muallif GROVER., manba
Oh, bu juda aqlli! : D rahmat, albatta, bu albatta yordam beradi
qo'shib qo'ydi muallif GROVER., manba
Ma'lumotlar bazasini so'rov qilishda buni SQL sifatida ishlatishga harakat qildim, ammo so'rovlar to'g'ri bajarilmayapti:/Buning sababi bormi? Bundan tashqari, odatdagidek, (masalan: SELECT , FROM , WHERE e.t.c) rangli bo'lmagani kabi,
qo'shib qo'ydi muallif GROVER., manba
UPDATE : So'rovimdan DECLARE @userId INT =?; ni olib tashlanganda esimda, formatlash ishlaydi.
qo'shib qo'ydi muallif GROVER., manba
Haha ha, men buni bilaman, tizimga kirgan foydalanuvchining qiymati bilan ? ni almashtirish uchun parametrlangan so'rovlardan foydalanmoqdaman.
qo'shib qo'ydi muallif GROVER., manba
Ajoyib! Xodimlar yarimi, lekin endi qaytib kelgan ma'lumotni chiqarishga harakat qilsam xatolarga duch kelyapmanmi? Har qanday fikr bormi? :/Taklif qilsam foreach ($ stmt-> natijalar ($ post)) {echo $ post-> postid} .
qo'shib qo'ydi muallif GROVER., manba
@GROVER Yo'q, faqatgina ? dan foydalanishni to'xtatish uchun o'zgaruvchini yaratdim. Turi muhim emas.
qo'shib qo'ydi muallif Orchidoris, manba
@GROVER ? amalga haqiqiy qiymatni kiritishingiz kerak
qo'shib qo'ydi muallif Orchidoris, manba
@GROVER Javob yangilandi. Odatda, men T-SQL bilan ishlayapman, shuning uchun MySql uchun noto'g'ri sintaksisi ishlatilgan.
qo'shib qo'ydi muallif Orchidoris, manba

Ichki qo'shilishlarni yaratishning klassik usuli, ko'proq o'qilishi mumkin va kod nima uchun ishlashini tushunishga yordam beradi. Bundan tashqari, bu SQL uchun kod konversiyasidir, shuning uchun ham sizni (men kabi) sizni tushunishga yordam beradi.

Kodni INNER JOIN dan foydalanish uchun qayta yozdim. Buni sinab ko'ring.

SELECT @userId := ?;

SELECT posts.*, users.*, friends.* 
FROM friends
JOIN users ON users.user_id = 
    CASE friends.userA
    WHEN @userId
    THEN friends.userB
    ELSE friends.userA END
JOIN posts ON posts.poster = users.user_id
WHERE friends.userA = @userId OR friends.userB = @userId
ORDER BY posts.post_id DESC LIMIT 20;

friends jadvali ichida dublar yo'qligiga ishonch hosil qiling. Quyidagi so'rovlar sizga yordam beradi:

SELECT User1, User2, COUNT(*) as DupeCount
FROM 
(
    SELECT
        CASE WHEN friends.userA < friends.userB THEN friends.userA ELSE friends.userB END AS User1,
        CASE WHEN friends.userA < friends.userB THEN friends.userB ELSE friends.userA END AS User2
    FROM friends
) AS F
GROUP BY User1, User2
HAVING COUNT(*) > 1
2
qo'shib qo'ydi
Rahmat, men buni sinab ko'raman! :) Nima uchun men userIdni INT deb e'lon qilishim kerak?
qo'shib qo'ydi muallif GROVER., manba
Oh, bu juda aqlli! : D rahmat, albatta, bu albatta yordam beradi
qo'shib qo'ydi muallif GROVER., manba
Ma'lumotlar bazasini so'rov qilishda buni SQL sifatida ishlatishga harakat qildim, ammo so'rovlar to'g'ri bajarilmayapti:/Buning sababi bormi? Bundan tashqari, odatdagidek, (masalan: SELECT , FROM , WHERE e.t.c) rangli bo'lmagani kabi,
qo'shib qo'ydi muallif GROVER., manba
UPDATE : So'rovimdan DECLARE @userId INT =?; ni olib tashlanganda esimda, formatlash ishlaydi.
qo'shib qo'ydi muallif GROVER., manba
Haha ha, men buni bilaman, tizimga kirgan foydalanuvchining qiymati bilan ? ni almashtirish uchun parametrlangan so'rovlardan foydalanmoqdaman.
qo'shib qo'ydi muallif GROVER., manba
Ajoyib! Xodimlar yarimi, lekin endi qaytib kelgan ma'lumotni chiqarishga harakat qilsam xatolarga duch kelyapmanmi? Har qanday fikr bormi? :/Taklif qilsam foreach ($ stmt-> natijalar ($ post)) {echo $ post-> postid} .
qo'shib qo'ydi muallif GROVER., manba
@GROVER Yo'q, faqatgina ? dan foydalanishni to'xtatish uchun o'zgaruvchini yaratdim. Turi muhim emas.
qo'shib qo'ydi muallif Orchidoris, manba
@GROVER ? amalga haqiqiy qiymatni kiritishingiz kerak
qo'shib qo'ydi muallif Orchidoris, manba
@GROVER Javob yangilandi. Odatda, men T-SQL bilan ishlayapman, shuning uchun MySql uchun noto'g'ri sintaksisi ishlatilgan.
qo'shib qo'ydi muallif Orchidoris, manba

So'rovda foydalanuvchi ? ning do'stlarini yozgan xabarlarni qaytarishi kerak deb o'ylayman. Avval do'stlaringizni, ularning postlarini, keyin boshqa ma'lumotlarni toping.

SELECT  pp.*, uu.* 
FROM     (select distinct case when ? = friends.userB then friends.userA else friends.userB end as user_id
         from friends 
         where ? in (friends.userA, friends.userB)
         and friends.areFriends = 1 
         ) f
join posts pp on pp.poster = f.user_id
join users uu on uu.user_id = pp.poster
1
qo'shib qo'ydi

So'rovda foydalanuvchi ? ning do'stlarini yozgan xabarlarni qaytarishi kerak deb o'ylayman. Avval do'stlaringizni, ularning postlarini, keyin boshqa ma'lumotlarni toping.

SELECT  pp.*, uu.* 
FROM     (select distinct case when ? = friends.userB then friends.userA else friends.userB end as user_id
         from friends 
         where ? in (friends.userA, friends.userB)
         and friends.areFriends = 1 
         ) f
join posts pp on pp.poster = f.user_id
join users uu on uu.user_id = pp.poster
1
qo'shib qo'ydi
PhP |BotsUz
PhP |BotsUz
93 ishtirokchilar

Phpni o'rganishni Hohlasangiz https://t.me/joinchat/AAAAAE-KRc5dd5tPMmGmWA A'zo bo'lin