Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ PostgreSQL _ [PostgreSQL] Dwukrotne zapytanie do jednej tabeli

Napisany przez: lecter007 11.06.2014, 12:06:05

Witam,

Mam tabele w której jest ponad 500 tys rekordow, które wyglądają tak:
id: | userid: | course: | element: | value:
1 | 2 | 45 | status | passed
2 | 2 | 45 | score | 96
3 | 3 | 56 | status | incomplete
4 | 4 | 54 | status | failed
5 | 4 | 54 | score | 30
6 | 3 | 56 | score | 67

Potrzebuję najpierw wybrać który user w którym course ma element='status' i value='passed' albo 'failed', a następnie, jeśli ma 'passed' albo 'failed' w danym kursie, wypisać value gdy element='score' w tym course.
Trochę to zawiłe ale mniejwięcej tak to wygląda smile.gif

Dzięki!


Napisany przez: Crozin 11.06.2014, 12:15:39

1. Masz zrypaną strukturę bazy na pierwszy rzut oka.
2. Zapytanie, które wyciągnie dane w "normalnej" formie:

  1. SELECT a.id, a.userid, a.course, a.value AS STATUS, b.value AS score
  2. FROM tbl_name a
  3. JOIN tbl_name b ON a.userid = b.userid AND a.course = b.course AND b.element = 'score'
  4. WHERE a.element = 'status' AND a.value IN('passed', 'failed');

Napisany przez: lecter007 11.06.2014, 13:20:05

Super, działa! Dzięki!

A czy dałoby się do tego jeszcze dołożyć wypisywanie tylko tych rekordów, których nie ma już w innej tabeli?
Generalnie jest tak, że pierwsze zapytanie wyszukuje rekordy (tak jak w poście powyżej) i wrzuca je do tabeli 'report'. A teraz chciałbym, żeby do tabeli 'report' dopisywane były tylko te rekordy, których tam jeszcze nie ma. Czyli powyższa kwerenda + LEFT JOIN? tylko jak questionmark.gif




Napisany przez: Crozin 11.06.2014, 13:31:24

  1. ... WHERE ... AND a.id NOT IN(SELECT id FROM other_table);
?

Napisany przez: lecter007 11.06.2014, 13:46:24

no właśnie id mi nie kopiuje z oryginalnej tabeli... musiałoby by być

  1. ...WHERE...AND a.userid NOT IN (SELECT userid FROM report) AND a.course NOT IN (SELECT course FROM report)... ale i tak jak dojdę do value TO nie pójdzie bo mam już wcześeniej a.value IN ('passed', 'failed') a musiałoby BYć a.value NOT IN (SELECT value FROM report)

Value też musi sprawdzać bo możliwe, że ktoś poprawił swój wynik i wtedy powinny być 2 wpisy w tabeli report - w oryginalnej tabeli aktualizuje się SCORE i STATUS.

Wiem, że ktoś to głupio wymyślił ale tak to już zastałem...

Z góry dzięki!

Napisany przez: Crozin 11.06.2014, 14:00:18

Napisz na podstawie jakich kolumn określasz czy dany rekord powinien zostać skopiowany czy nie. Być może chodzi o coś takiego?

  1. ... WHERE ... AND (a.userid, a.course) NOT IN(SELECT userid, course FROM other_table);

Napisany przez: lecter007 12.06.2014, 07:22:25

Dokładnie chce sprawdzać po 'course', 'value', 'userid'. Jeśli taki rekord istnieje w tabeli 'report', pomija go. Chodzi o to, że w pierwszej tabeli np. score może się zmienić - ktoś miał 90, a zmieniło mu się na 100 i chciałbym, żeby w tej drugiej tabeli (report) były wtedy 2 rekordy.

Próbowałem tak jak pisałeś w ostatnim poście, ale jakby w ogóle nie wziął pod uwagę tego warunku... wyświetla wszystkie rekordy...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)