Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Ostatni wpis (z grup i subgrup)
Forum PHP.pl > Forum > Bazy danych > MySQL
Mephis
Witam.

Posiadam coś takiego jak:
- grupy
  • id
  • nazwa

- debaty (należą do grup)
  • id
  • id_grupy
  • nazwa

- wpisy (należą do debat)
  • id
  • id_debaty
  • treść
  • data


Poniżej umieszczam zrzut bazy danych:
  1. CREATE DATABASE IF NOT EXISTS `test_lastentry` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
  2. USE `test_lastentry`;
  3.  
  4. CREATE TABLE `groups` (
  5. `group_id` tinyint(1) UNSIGNED NOT NULL,
  6. `name` varchar(65) NOT NULL
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  8.  
  9. CREATE TABLE `debates` (
  10. `debate_id` smallint(2) UNSIGNED NOT NULL,
  11. `group_fk` tinyint(1) UNSIGNED NOT NULL,
  12. `name` varchar(65) NOT NULL
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  14.  
  15. CREATE TABLE `entries` (
  16. `entry_id` smallint(2) UNSIGNED NOT NULL,
  17. `debate_fk` smallint(2) UNSIGNED NOT NULL,
  18. `content` varchar(65) NOT NULL,
  19. `date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
  20. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  21.  
  22. INSERT INTO `groups` (`group_id`, `name`) VALUES
  23. (1, 'group_one'),
  24. (2, 'group_second'),
  25. (3, 'group_third');
  26.  
  27. INSERT INTO `debates` (`debate_id`, `group_fk`, `name`) VALUES
  28. (1, 1, 'debate 1 for group 1'),
  29. (2, 2, 'debate 1 for group 2'),
  30. (3, 2, 'debate 2 for group 2'),
  31. (4, 2, 'debate 3 for group 2'),
  32. (5, 3, 'debate 1 for group 3'),
  33. (6, 3, 'debate 2 for group 3');
  34.  
  35. INSERT INTO `entries` (`entry_id`, `debate_fk`, `content`, `date`) VALUES
  36. (1, 1, 'entry 1 for debate 1', '2017-03-12 03:12:23'),
  37. (2, 1, 'entry 2 for debate 1', '2017-03-13 03:15:18'),
  38. (3, 2, 'entry 1 for debate 2', '2017-03-13 06:40:20'),
  39. (4, 2, 'entry 2 for debate 2', '2017-03-14 09:15:24'),
  40. (5, 3, 'entry 1 for debate 3', '2017-03-12 02:12:05'),
  41. (6, 3, 'entry 2 for debate 3', '2017-03-13 13:47:52'),
  42. (7, 3, 'entry 3 for debate 3', '2017-03-15 14:15:15'),
  43. (8, 4, 'entry 1 for debate 4', '2017-03-15 14:15:15'),
  44. (9, 5, 'entry 1 for debate 5', '2017-03-11 08:11:39'),
  45. (10, 5, 'entry 2 for debate 5', '2017-03-12 16:22:18'),
  46. (11, 6, 'entry 1 for debate 6', '2017-03-14 09:15:24');
  47.  
  48. ALTER TABLE `groups`
  49. ADD PRIMARY KEY (`group_id`);
  50. ALTER TABLE `debates`
  51. ADD PRIMARY KEY (`debate_id`);
  52. ALTER TABLE `entries`
  53. ADD PRIMARY KEY (`entry_id`);
  54.  
  55. ALTER TABLE `groups`
  56. MODIFY `group_id` tinyint(1) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
  57. ALTER TABLE `debates`
  58. MODIFY `debate_id` smallint(2) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
  59. ALTER TABLE `entries`
  60. MODIFY `entry_id` smallint(2) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12;


A tutaj zobrazowane dane:

GROUP - grupa
D - "debates" - debaty
E - "entries" - wpisy
last (X) - ostatni wpis w debacie (o czasie X)


Najpierw sprawa jest w miarę prosta.
Utworzyłem sobie listę "debat" wraz z danymi dot. ostatniego wpisu i wygląda to następująco:
  1. SELECT
  2. `d`.`debate_id`,
  3. `d`.`name`,
  4. `last_e`.*
  5. FROM `debates` AS `d`
  6. LEFT JOIN (
  7. SELECT
  8. `e`.`debate_fk`,
  9. `e`.`entry_id`,
  10. `e`.`content`,
  11. `e`.`date`
  12. FROM `entries` AS `e`
  13. INNER JOIN (
  14. SELECT
  15. `debate_fk`,
  16. MAX(`date`) AS `date`
  17. FROM `entries`
  18. GROUP BY `debate_fk`
  19. ) AS `last_e_pd` ON (
  20. (`last_e_pd`.`debate_fk` = `e`.`debate_fk`)
  21. AND (`last_e_pd`.`date` = `e`.`date`)
  22. )
  23. ) AS `last_e` ON (`last_e`.`debate_fk` = `d`.`debate_id`)

Dałoby się jakąś to uprościć? Jakieś uwagi?

Cóż chciałbym osiągnąć? Chciałbym pobrać listę grup (a nie dabat) wraz z danymi dot. ostatniego wpisu (i dot. debaty do której wpis ten należy) w grupie...
Czyli identyfikator i nazwę grupy, identyfikator, treść i datę ostatniego wpisu oraz identyfikator i nazwa debaty.

Przy liście z "debatami" sprawa była prosta o tyle, że pobierałem najwyższą wartość (date) i grupowałem wg. id debaty - tutaj otrzymywałem wymagany wynik.
Jeśli chciałbym do wpisów dołączyć tabelę debat (aby otrzymać z nich fk grupy), to grupując wg fk grupy nie otrzymam pożądanych wyników, ponieważ zgadzać będzie się id grupy, data ostatniego wpisu, ale id debaty zostanie wzięte pierwsze z brzegu (i nie będzie zgodny z oczekiwaniami... eh, gdyby tylko ten "MAX" wybierał cały wiersz a nie tylko komórkę).
Posiadając id grupy i datę ostatniego wpisu, nie mogę do tego dołączyć wpisów (co mógłbym zrobić tylko na podstawie daty), ponieważ jeśli wpisy z różnych debat będą mieć identyczny czas (mało prawdopodobne, ale jednak), to wynik będzie nieprawidłowy.

Czy ktoś borykał się z podobnym problemem? Miałby ktoś jakieś pomysły?

Proszę o pomoc.
javafxdev
"Chciałbym pobrać listę grup (a nie dabat) wraz z danymi dot. ostatniego wpisu (i dot. debaty do której wpis ten należy) w grupie..."
a potem:
"...ponieważ jeśli wpisy z różnych debat będą mieć identyczny czas (mało prawdopodobne, ale jednak), to wynik będzie nieprawidłowy..."

to co chciałbyś uzyskać jak jednak ten przypadek się zdarzy? listę dot. ostatnich wpisów czy jak niby to by miało działać?

Mephis
W tym pierwszym zapytaniu otrzymuję listę debat i połączone z nimi ostatnie wpisy:


Chcę uzyskać listę grup i połączone z nimi ostatnie wpisy (i debaty), czyli te wiersze:
  1. SELECT
  2. `g`.*,
  3. `d`.`debate_id`,
  4. `d`.`name`,
  5. `last_e`.`debate_fk`,
  6. `last_e`.`entry_id`,
  7. `last_e`.`content`,
  8. `last_e`.`date`
  9. FROM `groups` AS `g`
  10. LEFT JOIN `debates` AS `d` ON (`d`.`group_fk` = `g`.`group_id`)
  11. LEFT JOIN (
  12. SELECT
  13. `e`.`debate_fk`,
  14. `e`.`entry_id`,
  15. `e`.`content`,
  16. `e`.`date`
  17. FROM `entries` AS `e`
  18. INNER JOIN (
  19. SELECT
  20. `debate_fk`,
  21. MAX(`date`) AS `date`
  22. FROM `entries`
  23. GROUP BY `debate_fk`
  24. ) AS `last_e_pd` ON (
  25. (`last_e_pd`.`debate_fk` = `e`.`debate_fk`)
  26. AND (`last_e_pd`.`date` = `e`.`date`)
  27. )
  28. ) AS `last_e` ON (`last_e`.`debate_fk` = `d`.`debate_id`)



Lecz, w przypadku, kiedy chciałbym pogrupować wg. grupy i pobrać najwyższą wartość z daty (tak, jak robię to w przypadku listy debat):
  1. SELECT
  2. `g`.*,
  3. `d`.`debate_id`,
  4. `d`.`name`,
  5. `last_e`.`debate_fk`,
  6. `last_e`.`entry_id`,
  7. `last_e`.`content`,
  8. MAX(`last_e`.`date`) AS `date`
  9. FROM `groups` AS `g`
  10. LEFT JOIN `debates` AS `d` ON (`d`.`group_fk` = `g`.`group_id`)
  11. LEFT JOIN (
  12. SELECT
  13. `e`.`debate_fk`,
  14. `e`.`entry_id`,
  15. `e`.`content`,
  16. `e`.`date`
  17. FROM `entries` AS `e`
  18. INNER JOIN (
  19. SELECT
  20. `debate_fk`,
  21. MAX(`date`) AS `date`
  22. FROM `entries`
  23. GROUP BY `debate_fk`
  24. ) AS `last_e_pd` ON (
  25. (`last_e_pd`.`debate_fk` = `e`.`debate_fk`)
  26. AND (`last_e_pd`.`date` = `e`.`date`)
  27. )
  28. ) AS `last_e` ON (`last_e`.`debate_fk` = `d`.`debate_id`)
  29. GROUP BY `g`.`group_id`


...otrzymuję nieprawidłowe wyniki.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.