Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: skomplikowane zapytanie
Forum PHP.pl > Forum > Bazy danych > MySQL
Anna
Zapytanie powinno zwracać:
- dane wszystkich userów users_data.*
- sumę punktów zdobytych przez usera w danym teście SUM(users_asks.point)+SUM(answers.point), lub NULL jeśli user testu nie wypełniał
- maksymalną sumę punktów jaką user mógł zdobyć w danym teście

Macie jakieś pomysły? winksmiley.jpg

Kombinuję w ten sposób:

  1. SELECT users_data. * , ask.suma + ans.suma, ask.max + ans.max
  2. FROM users_data LEFT JOIN (
  3. SELECT SUM( users_asks.point ) AS suma, COUNT( asks.ask_id ) AS max, users_asks.user_id
  4. FROM users_asks, asks
  5. WHERE users_asks.ask_id = asks.ask_id
  6. GROUP BY users_asks.user_id, asks.test_id
  7. ) AS ask
  8. USING ( user_id )
  9. LEFT JOIN (
  10.  
  11. SELECT SUM( answers.point ) AS suma, COUNT( asks.ask_id ) AS max, users_answers.user_id
  12. FROM users_answers, answers, asks
  13. WHERE users_answers.answer_id = answers.answer_id AND answers.ask_id = asks.ask_id
  14. GROUP BY users_answers.user_id, asks.test_id
  15. ) AS ans
  16. USING ( user_id )


questionmark.gifquestionmark.gif
DeyV
podaj, proszę, uproszczoną strukturę tych tabel, wraz z przykładowymi danymi i oczekiwanymi wynikami.
Anna


  1. --
  2. -- Zrzut danych tabeli `answers`
  3. --
  4. INSERT INTO `answers` VALUES (1, 2, 'Odpowiedź dobra', 1, 1);
  5. INSERT INTO `answers` VALUES (2, 2, 'Odpowiedź zła', 0, 1);
  6. INSERT INTO `answers` VALUES (3, 3, 'Dobra odpowiedź do pytania I w teście II', 1, 1);
  7. INSERT INTO `answers` VALUES (4, 3, 'Zła odpowiedź do pytania I w teście II', 0, 1);
  8. -- --------------------------------------------------------
  9. --
  10. -- Zrzut danych tabeli `asks`
  11. --
  12. INSERT INTO `asks` VALUES (1, 1, 'Pytanie pierwsze w teście, na które musisz sam odpowiedzieć', 1);
  13. INSERT INTO `asks` VALUES (2, 1, 'Pytanie drugie', 1);
  14. INSERT INTO `asks` VALUES (3, 2, 'Pytanie I do testu II', 1);
  15. INSERT INTO `asks` VALUES (4, 2, 'Pytanie II do testu II', 1);
  16. -- --------------------------------------------------------
  17. --
  18. -- Zrzut danych tabeli `tests`
  19. --
  20. INSERT INTO `tests` VALUES (1, 'test nr 1', 60, 1);
  21. INSERT INTO `tests` VALUES (2, 'Test nr 2', 60, 1);
  22. -- --------------------------------------------------------
  23. --
  24. -- Zrzut danych tabeli `users_answers`
  25. --
  26. INSERT INTO `users_answers` VALUES (1, 1);
  27. INSERT INTO `users_answers` VALUES (3, 1);
  28. -- --------------------------------------------------------
  29. --
  30. -- Zrzut danych tabeli `users_asks`
  31. --
  32. INSERT INTO `users_asks` VALUES (1, 1, 'Moja wyczerpująca odpowiedź', 1);
  33. -- --------------------------------------------------------
  34. --
  35. -- Zrzut danych tabeli `users_data`
  36. --
  37. INSERT INTO `users_data` VALUES (1, 'Tester', 'Testowicz', NULL, NULL);
  38. INSERT INTO `users_data` VALUES (2, 'Marek', 'Konrad', marek@konrad.pl, NULL);


oczekiwane wyniki:

--------------------------------------------------------------------------
users_data.* |suma |max
--------------------------------------------------------------------------
1 | Tester | Testowicz | NULL | NULL | 2 | 2
1 | Tester | Testowicz | NULL | NULL | 1 | 2
2 | Marek | Konrad | marek@konrad.pl | NULL | NULL | NULL
--------------------------------------------------------------------------

Można też podejść do tematu inaczej i do testu dołączyć usera z wynikami:

--------------------------------------------------------------------------------------------
test.name | users_data.firstname | users_data.surname | suma | max
--------------------------------------------------------------------------------------------
test nr 1 | Tester | Testowicz | 2 | 2
test nr 2 | Tester | Testowicz | 1 | 2

--------------------------------------------------------------------------------------------
DeyV
Aniu - jesteś dla mnie niedobra. Przez Ciebie będę musiał sobie ręcznie utworzyć te tabelki...
Anna
Ależ proszę...

  1. --
  2. -- Struktura tabeli dla `answers`
  3. --
  4. CREATE TABLE `answers` (
  5. `answer_id` int(11) NOT NULL AUTO_INCREMENT,
  6. `ask_id` int(11) NOT NULL,
  7. `answer` text,
  8. `point` tinyint(4) DEFAULT NULL,
  9. `enable` tinyint(4) DEFAULT NULL,
  10. PRIMARY KEY (`answer_id`),
  11. KEY `answers_FKIndex1` (`ask_id`)
  12. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
  13. -- --------------------------------------------------------
  14. --
  15. -- Struktura tabeli dla `asks`
  16. --
  17. CREATE TABLE `asks` (
  18. `ask_id` int(11) NOT NULL AUTO_INCREMENT,
  19. `test_id` int(11) NOT NULL,
  20. `ask` text,
  21. `enable` tinyint(4) DEFAULT NULL,
  22. PRIMARY KEY (`ask_id`),
  23. KEY `asks_FKIndex1` (`test_id`)
  24. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
  25. -- --------------------------------------------------------
  26. --
  27. -- Struktura tabeli dla `tests`
  28. --
  29. CREATE TABLE `tests` (
  30. `test_id` int(11) NOT NULL AUTO_INCREMENT,
  31. `name` varchar(45) DEFAULT NULL,
  32. `timeout` int(11) DEFAULT NULL,
  33. `enable` tinyint(4) DEFAULT NULL,
  34. PRIMARY KEY (`test_id`)
  35. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
  36. -- --------------------------------------------------------
  37. --
  38. -- Struktura tabeli dla `users`
  39. --
  40. CREATE TABLE `users` (
  41. `user_id` int(11) NOT NULL AUTO_INCREMENT,
  42. `login` varchar(45) DEFAULT NULL,
  43. `passwd` varchar(45) DEFAULT NULL,
  44. `auth` tinyint(4) DEFAULT NULL,
  45. PRIMARY KEY (`user_id`)
  46. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
  47. -- --------------------------------------------------------
  48. --
  49. -- Struktura tabeli dla `users_answers`
  50. --
  51. CREATE TABLE `users_answers` (
  52. `answer_id` int(11) NOT NULL,
  53. `user_id` int(11) NOT NULL,
  54. PRIMARY KEY (`answer_id`,`user_id`),
  55. KEY `users_answers_FKIndex1` (`user_id`),
  56. KEY `users_answers_FKIndex2` (`answer_id`)
  57. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  58. -- --------------------------------------------------------
  59. --
  60. -- Struktura tabeli dla `users_asks`
  61. --
  62. CREATE TABLE `users_asks` (
  63. `user_id` int(11) NOT NULL,
  64. `ask_id` int(11) NOT NULL,
  65. `answer` text,
  66. `point` tinyint(4) DEFAULT NULL,
  67. PRIMARY KEY (`user_id`,`ask_id`),
  68. KEY `users_asks_FKIndex1` (`user_id`),
  69. KEY `users_asks_FKIndex2` (`ask_id`)
  70. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  71. -- --------------------------------------------------------
  72. --
  73. -- Struktura tabeli dla `users_data`
  74. --
  75. CREATE TABLE `users_data` (
  76. `user_id` int(11) NOT NULL,
  77. `firstname` varchar(45) DEFAULT NULL,
  78. `surname` varchar(45) DEFAULT NULL,
  79. `email` varchar(45) DEFAULT NULL,
  80. `phone` varchar(45) DEFAULT NULL,
  81. PRIMARY KEY (`user_id`),
  82. KEY `users_data_FKIndex1` (`user_id`)
  83. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Myślałam, że uda się coś "na sucho" wykombinować smile.gif
DeyV
na sucho nieco niezdrowo - czasem dziwne wyniki wychodzą smile.gif

Z tej struktury nie rozumiem jeszcze tylko jednej rzeczy.

W tabeli users_asks pojawiają się point. Jak te punkty mają się do maksymalnej ilości punktów, którą user może zdobyć w danym teście, którą przecież wyliczamy w oparciu o odpowiedzi danego usera zapisane w tabeli users_answers?
Anna
Co do struktury - nie wiem czy jest optymalna, ale póki co, nie widzę tego inaczej.

users_answers - odpowiedzi wybrane przez usera z answers (checkbox);
users_asks - odpowiedzi usera, na pytania, które nie mają gotowej odpowiedzi do wyboru (textarea)

Za maksymalną liczbę punktów można chyba potraktować count(asks.ask_id).
DeyV
Ok. Wyszło mi z tego coś takiego.

  1. SELECT u_d.user_id,
  2.  
  3. t.test_id,
  4.  
  5. SUM( an.point ) AS MAKS,
  6.  
  7. ( SELECT SUM( users_asks.point ) FROM users_asks LEFT JOIN asks ON (asks.ask_id= users_asks.ask_id )
  8. WHERE users_asks.user_id = u_d.user_id AND asks.test_id = t.test_id ) AS users_asks_point,
  9.  
  10. ( SELECT SUM( answers.point ) FROM users_answers INNER JOIN answers ON ( answers.answer_id = users_answers.answer_id )
  11. INNER JOIN asks ON ( asks.ask_id = answers.ask_id AND asks.test_id = t.test_id )
  12. WHERE users_answers.user_id = u_d.user_id
  13. ) AS users_answers_point
  14.  
  15. FROM tests t
  16. LEFT JOIN users_data u_d ON ( TRUE )
  17.  
  18. LEFT JOIN asks ON ( asks.test_id = t.test_id )
  19. LEFT JOIN answers an ON ( an.ask_id= asks.ask_id )
  20.  
  21. GROUP BY u_d.user_id, t.test_id


Jedna uwaga. U siebie mam tylko MySQL 4, który nie pozwala na SubQuery, więc musiałem przetestować to zapytanie na bazie Postgres. Niestety - nie wiem, co tak naprawdę w tej chwili potrafi MySQL 5 - ponoć dużo, więc zapytanie tego typu powinno chodzić poprawnie. Jednak głowy nie dam winksmiley.jpg
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.