only full group by aneb, něco mi uteklo?

- kleinpetr
- Člen | 480
Ahoj chci se zeptat co je špatného na tomto sql dotazu, který jsem normálně používal, ale najednou mi začal házet chybu, měnilo se něco v nette ? Díky za pomoc
SELECT *
FROM `table`
WHERE (DATE(`createdDate`) <= CURDATE() + 7)
GROUP BY DAY(`createdDate`)
ORDER BY `createdDate` DESC
error:
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'table.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
Editoval kleinpetr (8. 1. 2016 7:56)

- PetrHH
- Člen | 49
Vyřešeno:
$db->query('SET sql_mode = ""');
Toto neni dobry napad. Tim odstranite i dalsi nastaveni. U mne na MySQL 5.7 vrati select @@sql_mode toto:
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Lepsi je pouzit:
$db->query("SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''))");

- kleinpetr
- Člen | 480
Dnes jsem opět narazil na stejný problém a v podstatě na něj narazím vždy když použiji GROUP_BY
tabulka
messages
idMessage idUserRecipient idUserSender
1 4 2
2 4 2
sql dotaz
SELECT *
FROM `messages`
WHERE (`idUserRecipient` = 4)
GROUP BY `idUserRecipient`
ORDER BY `idMessage DESC`
V čem je problém ? Díky
Editoval kleinpetr (12. 5. 2016 13:38)

- Unlink
- Člen | 298
Ako píše @CZechBoY, toto nesúvisí s nette, takže lepšie bude použiť google, napr. https://stackoverflow.com/…n-each-group

- kleinpetr
- Člen | 480
Díky, ale to asi úplně neřeší můj problém.. Zkoušel jsem něco takového
SELECT (
SELECT *
FROM `message_user`
WHERE `idUserSender` = `user.id` OR `idUserRecipient` = `user.id`
ORDER BY `idMessage` DESC
LIMIT 1) AS `message`
FROM `user`
LEFT JOIN `message_user` ON `user`.`id` = `message_user`.`idUserRecipient`
WHERE (`message_user`.`idUserRecipient` = 5 OR `message_user`.`idUserSender` = 5)
Výsledek má být např. takovýhle
Petr Klein
uživatel: Ahoj jak se máš ? v 10:00
Jan Novák
vy: máš zítra čas ? v 15:20
Tudíž vytáhnout poslední zprávu ze spojení uživatel:uživatel
Editoval kleinpetr (13. 5. 2016 12:36)

- PetrHH
- Člen | 49
Mohlo by fungovat neco takoveho. Bohuzel nemam struktury. nemohu poradit vice
select max(message_user.idMessage),message_user.msg from user
LEFT JOIN
message_user ON user.id = message_user.idUserRecipient
WHERE
(message_user.idUserRecipient = 5 OR message_user.idUserSender = 5)
ve sloupsi message_user.msg je ulozena vlastni zprava, kterou potrebujete zobrazit.

- kleinpetr
- Člen | 480
Takže, sice to nějaké záznamy vrací, ale chová se to zvláštně..
tabulky
user
id, name, ...
message
id, date, message
message_user
idMessage, idUserRecipient, idUserSender, read
To je vše.. Co potřebuji:
Já jsem přihlášený uživatel a mám ID 5 nyní když
půjdu do inboxu, tak bych chtěl zobrazit seznam zpráv viz. gmail, vpodstatě
jste v doručených, ale vidíte i svou poslední odpověď. Co se týče
vláken, tak to neřeším, mám zkrátka jedno vlákno tudíž stejně jako
v telefonu messages.
Nyní tedy zjednodušeně potřebuji vytáhnout veškeré uživatele se kterými jsem já, jakožto ID 5, ve vztahu buďto jako příjemce nebo jako odesílatel a vypsat jejich seznam, to by šlo, jenže ke každému tomu uživateli potřebuji vytáhnout poslední známou vazbu z tabulky message_user, tudíž nejvyšší IdMessage a zároveň ty uživatele podle idMessage poslední zprávy seřadit.
Můj pokus dle vašeho návrhu byl takovýhle
SELECT
max(`message_user`.`idMessage`)
`message`.`message` AS `lastMessageContent`,
`message`.`date` AS `lastMessageDate`,
`message_user`.`read` AS `lastMessageRead`,
`user`.`id`,
`user`.`name`
FROM `user`
LEFT JOIN `message_user` ON `user`.`id` = `message_user`.`idUserRecipient`
LEFT JOIN `message` ON `message_user`.`idMessage` = `message`.`id`
WHERE (`message_user`.`idUserRecipient` = 5 OR `message_user`.`idUserSender` = 5)
ale to vypisovalo první zprávu ve vlákně, když jsem max odstranil, tak to zobrazuje pouze poslední odeslanou zprávu a je to takové zamícháné, že místo jména uživatele je mé jméno apod..
Díky za nápady a hlavně za váš čas.
Editoval kleinpetr (18. 5. 2016 0:44)

- Unlink
- Člen | 298
Nejako takto
SELECT
u1.id, u1.name,
u2.id AS lastMessageSenderId, u2.name AS lastMessageSenderName,
mu1.read,
message.`date`, message.message
FROM message_user mu1
LEFT JOIN message_user mu2 ON (
(
(mu2.idUserRecipient = mu1.idUserRecipient AND mu2.idUserSender = mu1.idUserSender)
OR (mu2.idUserRecipient = mu1.idUserSender AND mu2.idUserSender = mu1.idUserRecipient)
) AND mu1.idMessage < mu2.idMessage
)
LEFT JOIN message ON (message.id = mu1.idMessage)
LEFT JOIN user u1 ON (u1.id = IF(mu1.idUserRecipient = 1, mu1.idUserSender, mu1.idUserRecipient))
LEFT JOIN user u2 ON (u2.id = mu1.idUserSender)
WHERE (mu1.idUserRecipient = 1 OR mu1.idUserSender = 1) AND mu2.idMessage IS NULL
ORDER BY mu1.idMessage DESC
S tým, že ak nepotrebuješ aj meno odosielateľa poslednej správy, tak ten druhý join na user tabuľku môžeš vyhodiť.
Každopádne, pri pár záznamoch to nemá problém, ale ak budeš mať tých
záznamov veľa, tak sa bojím že to výkonovo padne.
Hlavným problémom je tá časť:
(mu2.idUserRecipient = mu1.idUserRecipient AND mu2.idUserSender = mu1.idUserSender)
OR (mu2.idUserRecipient = mu1.idUserSender AND mu2.idUserSender = mu1.idUserRecipient)
Ktorá znemožní využitie akého koľvek indexu.
Zlepšiť by sa to dalo využitím nejakých „threadov“, pretože ak by sa to nejoinovalo pomocou tohto výrazu, ale pomocou nejakého threadId tak by sa využili indexy a nebolo by to až tak zlé.
Každopádne, namiesto tohto by som skôr odporúčal vytvoriť nejakú pomocnú tabuľku, ktorá pre každého používateľa bude udržovať zoznam posledných správ…
EDIT:
Dalo by sa tomu pomôcť ale tiež to nieje nejaké extra výhra
SELECT
u1.id, u1.name,
u2.id AS lastMessageSenderId, u2.name AS lastMessageSenderName,
mu1.read,
message.`date`, message.message
FROM message_user mu1
LEFT JOIN message_user mu2 ON (
(
(mu2.idUserRecipient = mu1.idUserRecipient AND mu2.idUserSender = mu1.idUserSender)
) AND mu1.idMessage < mu2.idMessage
)
LEFT JOIN message_user mu3 ON (
(
(mu3.idUserRecipient = mu1.idUserSender AND mu3.idUserSender = mu1.idUserRecipient)
) AND mu1.idMessage < mu3.idMessage
)
LEFT JOIN message ON (message.id = mu1.idMessage)
LEFT JOIN user u1 ON (u1.id = IF(mu1.idUserRecipient = 1, mu1.idUserSender, mu1.idUserRecipient))
LEFT JOIN user u2 ON (u2.id = mu1.idUserSender)
WHERE (mu1.idUserRecipient = 1 OR mu1.idUserSender = 1) AND mu2.idMessage IS NULL AND mu3.idMessage IS NULL
ORDER BY mu1.idMessage DESC
Editoval Unlink (18. 5. 2016 8:54)

- kleinpetr
- Člen | 480
Takže výsledek je takový:
do tabulky message_user jsem přidal sloupec ID a vytvořil jsem pomocnou tabulku
message_user_last
idMessageUser idUser1 idUser2
pokud uzivatel napise nekomu zpravu napr. 4 ⇒ 5, tak vyhledam vztah
WHERE idUser1 = 4 AND idUser2 = 5 OR idUser1 = 5 AND idUser2 = 4
To mi vrátí záznam s id na poslední zprávu, aktuální zprávu uložím
a updatnu záznam o nové id.
Pokud neexistuje tak ho vytvořím, ve finále tu tabulku procházím a
dotahávám si z ní potřebné data přes cizí klíče + podmínkou
zjišťuji zda jsem jako přihlášený user v té poslední zprávě jako
sender nebo recipient a podle toho si vytáhnu data z usera, které
potřebuji.
Takže finální dotaz vypadá nějak takhle
SELECT
IF(`messageUser`.`idUserRecipient` = 4,`idUserSender`.`name`,`idUserRecipient`.`name`) AS `otherUserName`,
IF(`messageUser`.`idUserRecipient` = 4,`messageUser`.`idUserSender`,`messageUser`.`idUserRecipient`) AS `otherUserId`,
IF(`messageUser`.`idUserSender` = 4, 1, 0) AS `iAmSender`,
`messageUser`.*,
`message`.*
FROM `message_user_last`
LEFT JOIN `message_user` `messageUser` ON `message_user_last`.`idMessageUser` = `messageUser`.`id`
LEFT JOIN `message` ON `messageUser`.`idMessage` = `message`.`id`
LEFT JOIN `user` `idUserSender` ON `messageUser`.`idUserSender` = `idUserSender`.`id`
LEFT JOIN `user` `idUserRecipient` ON `messageUser`.`idUserRecipient` = `idUserRecipient`.`id`
WHERE (`idUser1` = 4 OR `idUser2` = 4)
ORDER BY `message`.`date` DESC
Nepodařilo se mi nějak sloučit podmínky v SELECTU kdyby někdo věděl, tak určitě přivítám :)
Díky moc za pomoc a možná se to bude někomu hodit :)
Editoval kleinpetr (19. 5. 2016 0:30)