Oskar S.

Oskar S. Inżynier Serwisu

Temat: PLSQL pomoc w budowie zapytania.

Witam potrzebuję pomocy w doklejeniu w niżej podanym zapytaniu, treści która umożliwi wyświetlenie pozycji które pojawiały się na Izbie przyjęć więcej niż raz w okresie 72h .

SELECT
p.nazwisko as "Nazwisko", p.imiona as "Imiona", j.nazwa as "JOS",
wm_concat(op.ks_odm_nr||'/'||op.ks_odm_rok) as "Nr"
from
pacjent p, pobyt po, jos j, odm_porada op
where
po.id_opi = op.id_opi and
PO.IDK_JOS = J.IDK_JOS and
P.ID_PAC = PO.ID_PAC and
PO.STATUS = 'ODM' and
PO.DT_OD>='2014-01-01' and po.dt_od<'2014-02-01'
group by po.status, p.nazwisko, p.imiona, j.nazwa
having count(op.ks_odm_nr)>'1'
order by "Nazwisko"

Temat: PLSQL pomoc w budowie zapytania.

Hm, czy istnieje ryzyko, że jeśli Ci pomogę, a popełnię błąd, którego ty nie wyłapiesz, to któregoś z pacjentów może to kosztować zdrowie/życie?

konto usunięte

Temat: PLSQL pomoc w budowie zapytania.

Cześć,

wystarczy dokleić warunek:
AND DataPrzyjęcia >= sysdate - 3

Pozdrawiam
Marcin Mackiewicz

Marcin Mackiewicz Programista JAVA, RS
Adware Polska

Temat: PLSQL pomoc w budowie zapytania.

Marcin K.:
Cześć,

wystarczy dokleić warunek:
AND DataPrzyjęcia >= sysdate - 3

Pozdrawiam

Ja tu rozumiem, że należy sprawdzić czy dla wizyt w zadanym przedziale dat są powtórki, które pojawiają się w czasie mniejszym niż 72h. Zrobienie takiego zapytania wyświetli wszystkie wiersze starsze niż 3 dni ale nie sprawdzi ilości powtórek.
Bez testów (zapytanie może zawierać błędy) bo:
- Nie ma info o tym jaka do baza danych
- Brak struktur tabel i przykładowych danych

Ja bym zrobił np tak:
SELECT 
-- Wiersze wyswietlajace sie swiadcza o przynajmniej jednej dodatkowej wizycie w ciagu 72h.
-- Kazdy dodatkowy taki sam wiersz swiadczy o 3, 4 i kolejniej wizycie. Interesuje nas fakt
-- odbycia przynajmniej jednej takiej wizyty wiec dublety mozna pominac.
DISTINCT
p.nazwisko AS "Nazwisko",
p.imiona AS "Imiona",
j.nazwa AS "JOS",
wm_concat(op.ks_odm_nr||'/'||op.ks_odm_rok) AS "Nr"
-- Dla kazdego pacjenta
FROM
pacjent p
-- Szukam wizyt
JOIN
pobyt po ON p.id_pac = po.id_pac
-- Dla znalezionych wizyt szukam przynajmniej jednej innej wizyty odbytej do 72h wczesniej
LEFT JOIN
pobyt p2 ON p.id_pac = p2.id_pac AND (p2.dt_od >= po.dt_od - INTERVAL 72 HOUR AND p2.dt_od < po_dt_od)
JOIN
jos j ON po.idk_jos = j.idk_jos
JOIN
odm_porada op ON po.id_opi = od.id_opi
WHERE
-- Wizyta o statusie
po.status = 'ODM'
-- Odbywana pomiedzy datami
AND po.dt_od BETWEEN '2014-01-01' AND '2014-01-31'
-- I znaleziono inne wizyty do 72h wczesniej
AND p2.id_pac IS NOT NULL
ORDER BY
p.nazwisko

Do statusów się przyczepiam. Uważam, że powinny być tabelą słownikową i status o konkretnym kodzie "ODM' powinien mieć swój odpowiednik liczbowy ze słownika.

konto usunięte

Temat: PLSQL pomoc w budowie zapytania.

Według mnie było dobrze. Zapytanie grupowało po
group by po.status, p.nazwisko, p.imiona, j.nazwa
z having count(op.ks_odm_nr)>'1'
Marcin Mackiewicz

Marcin Mackiewicz Programista JAVA, RS
Adware Polska

Temat: PLSQL pomoc w budowie zapytania.

Marcin K.:
Według mnie było dobrze. Zapytanie grupowało po
group by po.status, p.nazwisko, p.imiona, j.nazwa
z having count(op.ks_odm_nr)>'1'

Może czegoś nie rozumiem..,
Zakładam, że po.dt_od to data przyjęcia bo wtedy następuje początek wizyty. Zapytanie SQL wyciąga dane za styczeń 2014... Jak dorzucisz do WHERE "AND dataPrzyjęcia >= sysdate - 3" to na dzień dzisiejszy dostaniesz pusty zbiór bo szukamy za styczeń. A gdzie jest taka kolumna jak "dataPrzyjęcia"? Nie widziałem jej w zapytaniu. Czy to oznacza, że mam sobie taką wyimaginować?

A przypadek testowy?
Uzupełnię pacjenta A. Dodam mu wizytę A1 od 2014-01-02 + wpis do tabeli jos i odm_porada. Dodam wizytę A2 od 2014-01-18 + wpis do tabeli jos i odm_porada.

Wybieram dane za styczeń... grupuję... i podliczam... dla pacjenta A podliczy mi 2 wizyty... Co z tego że są w odstępie 16 dni.

Przypadek testowany na PostgreSQL 9.3 z następującą strukturą danych oraz danymi w obiektach:
DROP TABLE IF EXISTS odm_porada;
DROP TABLE IF EXISTS pobyt;
DROP TABLE IF EXISTS jos;
DROP TABLE IF EXISTS pacjent;

CREATE TABLE pacjent(
id_pac int,
nazwisko text,
imiona text,
CONSTRAINT pacjent_pkey PRIMARY KEY (id_pac)
);

CREATE TABLE jos(
idk_jos int,
nazwa text,
CONSTRAINT jos_pkey PRIMARY KEY (idk_jos)
);

CREATE TABLE pobyt(
id_opi int,
id_pac int,
idk_jos int,
status text,
dt_od date,
CONSTRAINT pobyt_pkey PRIMARY KEY (id_opi),
CONSTRAINT pobyt_fkey1 FOREIGN KEY (id_pac)
REFERENCES pacjent (id_pac) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT pobyt_fkey2 FOREIGN KEY (idk_jos)
REFERENCES jos (idk_jos) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT
);

CREATE TABLE odm_porada(
id_opi int,
ks_odm_nr int,
ks_odm_rok int,
CONSTRAINT odm_porada_pkey PRIMARY KEY (id_opi),
CONSTRAINT odm_porada_fkey FOREIGN KEY (id_opi)
REFERENCES pobyt (id_opi) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
);

INSERT INTO jos VALUES (1, 'JOS 1');
INSERT INTO jos VALUES (2, 'JOS 2');

INSERT INTO pacjent VALUES (1, 'Kowalski', 'Jan');
INSERT INTO pacjent VALUES (2, 'Nowak', 'Tomasz');

INSERT INTO pobyt VALUES (1, 1, 1, 'ODM', '2014-01-02');
INSERT INTO pobyt VALUES (2, 1, 1, 'ODM', '2014-01-18');
INSERT INTO pobyt VALUES (3, 2, 2, 'ODM', '2014-01-02');
INSERT INTO pobyt VALUES (4, 2, 2, 'ODM', '2014-01-03');
INSERT INTO pobyt VALUES (5, 2, 2, 'ODM', '2014-01-04');

INSERT INTO odm_porada VALUES (1, 1, 2014);
INSERT INTO odm_porada VALUES (2, 2, 2014);
INSERT INTO odm_porada VALUES (3, 3, 2014);
INSERT INTO odm_porada VALUES (4, 4, 2014);
INSERT INTO odm_porada VALUES (5, 5, 2014);

Zytpytanie osoby pytającej dostosowane do PostgreSQL + twoja propozycja "po.dt_od = sysdate - 3" podmieniona na odpowiednik w pg "po.dt_od = NOW()::DATE - 3
SELECT
p.nazwisko as "Nazwisko", p.imiona as "Imiona", j.nazwa as "JOS",
concat(op.ks_odm_nr||'/'||op.ks_odm_rok) as "Nr"
from
pacjent p, pobyt po, jos j, odm_porada op
where
po.id_opi = op.id_opi and
PO.IDK_JOS = J.IDK_JOS and
P.ID_PAC = PO.ID_PAC and
PO.STATUS = 'ODM' and
PO.DT_OD>='2014-01-01' and po.dt_od<'2014-02-01'
AND PO.DT_OD >= NOW()::DATE - 3
group by po.status, p.nazwisko, p.imiona, j.nazwa, op.ks_odm_nr, op.ks_odm_rok
having count(op.ks_odm_nr)>'1'
order by "Nazwisko"

Dla zadanych danych zwraca pusty zbiór - oczekiwany przeze mnie rezultat.

Po analizie z przykładowymi danymi moje zapytanie z poprzedniego postu zawierało błąd. Zwracane rekordy dublowały się ze względu na poradę z tabeli odm_porada w przypadku kiedy wizyt w ciągu 72h było więcej niż 2.
Numery porad/opinii zostały wrzucone jako string do jednej kolumny.
Ostateczne zapytanie wyciągające te dane wygląda tak:
SELECT 
nazwisko AS "Nazwisko",
imiona AS "Imiona",
nazwa AS "JOS",
ARRAY_TO_STRING(ARRAY_AGG(nr), ', ') AS "Nr"
-- Dla kazdego pacjenta
FROM (
SELECT DISTINCT
p.nazwisko, p.imiona, j.nazwa, concat(op.ks_odm_nr||'/'||op.ks_odm_rok) AS nr
FROM
pacjent p
-- Szukam wizyt
JOIN
pobyt po ON p.id_pac = po.id_pac
-- Dla znalezionych wizyt szukam przynajmniej jednej innej wizyty odbytej do 72h wczesniej
LEFT JOIN
pobyt p2 ON p.id_pac = p2.id_pac AND (p2.dt_od >= po.dt_od - INTERVAL '72 HOURS' AND p2.dt_od < po.dt_od)
JOIN
jos j ON po.idk_jos = j.idk_jos
JOIN
odm_porada op ON po.id_opi = op.id_opi
WHERE
-- Wizyta o statusie
po.status = 'ODM'
-- Odbywana pomiedzy datami
AND po.dt_od BETWEEN '2014-01-01' AND '2014-01-31'
-- I znaleziono inne wizyty do 72h wczesniej
AND p2.id_pac IS NOT NULL
) AS p
GROUP BY
nazwisko, imiona, nazwa
ORDER BY
p.nazwisko;

Zapytanie zwraca pana "Nowaka" ponieważ w trzech kolejnych dniach zanotowano pobyt. Pan "Kowalski" nie został zwrócony ponieważ odstęp pomiędzy zanotowanymi pobytami wynosił więcej niż 72h.



Wyślij zaproszenie do