HSQLDB v.2.3.0: USING predicate working as intended? - sql

The following query when executed against snapshot 50 of HSQLDB 2.3.0 produces an error. The error message is "Error: duplicate column name in derived table: INST_ID"
SELECT c.lastname, to_date_string(c.dob), i.itag|| ': ' ||
m.mrn, to_date_string(en.dofs),
to_date_string(en.dols), pa.payertag,
y.dxname, d.icd9, d.icd10, d.icd10name,
to_datetime_string(s.dos), r.cpt, r.rxname, p.lastname || ', ' ||
p.firstname
FROM Encounters AS en
INNER JOIN Clients AS c USING ( cli_id )
INNER JOIN Client_MRNs AS m ON c.defmrn_id = m.mrn_id
INNER JOIN Institutions AS i USING ( inst_id )
INNER JOIN Payers AS pa USING ( payer_id )
INNER JOIN Encounter_DXs AS x USING ( enc_id )
INNER JOIN Diagnoses AS d USING ( dx_id )
INNER JOIN DXSynonyms AS y ON d.defsyn_id = y.syn_id
INNER JOIN Services AS s USING ( enc_id )
INNER JOIN RXCodes AS r USING ( rx_id )
INNER JOIN Providers AS p USING ( prov_id )
WHERE (s.dos >= 56453 AND s.dos < 56461)
ORDER BY c.lastname, en.dofs, s.dos;
However, when I execute the same query but replace all the USING predicates with ON ... = phrases it executes successfully:
SELECT c.lastname, to_date_string(c.dob), i.itag|| ': ' ||
m.mrn, to_date_string(en.dofs),
to_date_string(en.dols), pa.payertag,
y.dxname, d.icd9, d.icd10, d.icd10name,
to_datetime_string(s.dos), r.cpt, r.rxname, p.lastname || ', ' ||
p.firstname
FROM Encounters AS en
INNER JOIN Clients AS c ON c.cli_id = en.cli_id
INNER JOIN Client_MRNs AS m ON c.defmrn_id = m.mrn_id
INNER JOIN Institutions AS i ON i.inst_id = m.inst_id
INNER JOIN Payers AS pa ON pa.payer_id = en.payer_id
INNER JOIN Encounter_DXs AS x ON x.enc_id = en.enc_id
INNER JOIN Diagnoses AS d ON d.dx_id = x.dx_id
INNER JOIN DXSynonyms AS y ON d.defsyn_id = y.syn_id
INNER JOIN Services AS s ON s.enc_id = en.enc_id
INNER JOIN RXCodes AS r ON r.rx_id = s.rx_id
INNER JOIN Providers AS p ON p.prov_id = s.prov_id
WHERE (s.dos >= 56453 AND s.dos < 56461)
ORDER BY c.lastname, en.dofs, s.dos;
Is this working as intended? I like using USING because it results in less verbose, cleaner code. I won't include the DDL for the tables right now (but can), because the queries are big and involve many tables, but there are three tables that have INST_ID fields. One table has it as the primary key, and the other two have foreign keys to it. Really the only difference in the queries is "ON" vs "USING".

After the first join, there is one INST_ID from ENCOUNTERS. After the second join, there is an additional one from CLIENTS_MRNS. The third join fails because of this duplication.

Related

Get all data for an entity from another table in one query

I have this query
select *
from (
select c.*,p.name as project_name,u.firstname || ' ' || u.lastname as fullname, u.email as owner_email, u.payment_method, u as user, u.id as user_id, u.api_id, u.api_key,
v.name as vendor_name, v.exid as vendor_id, s.number as sim_number, vm.exid as vendor_model_id, vm.name as vendor_model_name, cr.status as is_recording,
cr.storage_duration as cloud_recording_storage_duration, cr.schedule as schedule, cr.frequency as frequency,
(select count(id) as total from camera_shares cs where c.id=cs.camera_id) as total_share
from cameras c
inner JOIN users u on c.owner_id = u.id
left JOIN projects p on c.project_id = p.id
left JOIN sims s on c.id = s.camera_id
left JOIN vendor_models vm on c.model_id = vm.id
left JOIN vendors v on vm.vendor_id = v.id
left JOIN cloud_recordings cr on c.id = cr.camera_id
) c
this gives me all cameras and with all relevant values which I require.
now there is another table, snapshot_extractors and it has a relation with the camera on id and camera_id in extractors table, as one camera can have more than 1 extractors.
In the above query, I want to get all extraction for one camera, I can do it in a separate query, but is it possible to get all extractions in the above query as an array of all extractions for a camera?
You can use another correlated subquery:
(select array_agg(e.extraction)
from snapshot_extractors e
where e.camera_id = c.camera_id
)

PostgreSQL select multiple columns of a table that is connected via a many-to-many pivot

I have this query:
SELECT
a.account_uuid,
a.account_no,
a.account_group_uuid,
a.account_scope_uuid,
a.created_at,
a.deleted_at,
s.service_uuid,
s.status,
st.service_type,
(
SELECT
c.company
FROM companies c
WHERE a.company_owner_uuid = c.company_uuid
)
FROM
accounts a
LEFT JOIN
services s
ON a.account_uuid = s.account_uuid
LEFT JOIN
service_types st
ON s.service_type_uuid = st.service_type_uuid
WHERE
a.deleted_at IS NULL
ORDER BY
a.account_no
And I need to join and select multiple columns from a people table by way of a pivot table accounts_contacts that would have the account_uuid and a person_uuid. There are also is_primary and is_active columns on the accounts_contacts table and there will only be one primary at a time, so the end result would be a single first and last name. This is the idea of the query:
SELECT
p.first_name, p.last_name
FROM
people p
INNER JOIN
accounts_contacts ac
ON ac.account_uuid = a.account_uuid
AND ac.person_uuid = p.person_uuid
WHERE
ac.is_primary = true
AND ac.is_active = true
But not sure how to fit it into the above query. A subquery would only allow for one of the columns.
account_contacts is an "association" or "junction" table. It is not a pivot table.
The basic idea should be joins:
SELECT . . . ,
p.first_name, p.last_name
FROM accounts a LEFT JOIN
services s
ON a.account_uuid = s.account_uuid LEFT JOIN
service_types st
ON s.service_type_uuid = st.service_type_uuid LEFT JOIN
accounts_contacts ac
ON ac.account_uuid = a.account_uuid LEFT JOIN
people p
ON ac.person_uuid = p.person_uuid AND
ac.is_primary = true AND
ac.is_active = true

Return rows where a customer bought things on same day

Can someone help me with the rest of my Query.
This query gives me Customer, AdressNr, Date, Employee, Article, ActivityNr
from all the sales in my Company.
SELECT ad.Name + ' ' + ad.Vorname AS Customer,
pa.Kunde AS CustomerNr,
CONVERT(VARCHAR(10),p.datum,126) AS Date,
(SELECT a.name + ' ' + a.Vorname AS Name FROM PRO_Mitarbeiter m LEFT JOIN ADR_Adressen a ON a.AdressNrADR=m.AdressNrADR WHERE m.MitNrPRO = l.MitNrPRO) as Employee,
p.Artikel_1 AS Article,
l.AufgabenNrCRM AS OrderNr
FROM ZUS_Therapie_Positionen p
INNER JOIN CRM_AufgabenLink l ON l.AufgabenNrCRM = p.Id_Aktivitaet
INNER JOIN CRM_Aufgaben ab ON ab.AufgabenNrCRM = p.Id_Aktivitaet
INNER JOIN PRO_Auftraege pa ON pa.AuftragNrPRO = ab.AuftragNrPRO
INNER JOIN ADR_Adressen ad ON ad.AdressNrADR = pa.Kunde
INNER JOIN ADR_GruppenLink gl ON gl.AdressNrADR = ad.AdressNrADR
INNER JOIN ADR_Gruppen g ON g.GruppeADR = gl.GruppeADR
WHERE l.MitNrPRO != 0
GROUP BY l.AufgabenNrCRM,ad.Name,ad.Vorname,pa.Kunde,p.datum,p.Artikel_1,l.MitNrPRO
ORDER BY pa.Kunde,p.datum,l.AufgabenNrCRM
My goal is to filter this so i get only rows back where the customer has bought more then 1 Thing on the same day. It doesn't matter if a customer bought the same Article twice on the same day. I want too see this also.
It's to complicated to write some SQL Fiddle for you but in this Picture you can see what my goal is. I want to take away all rows with an X on the left side and thoose with a Circle i want to Keep.
As I don't speak German, I won't target this specifically to your SQL. But see the following quasi-code for a similar example that you should be able to apply to your own script.
SELECT C.CustomerName, O.OrderDate, O.OrderNumber
FROM CUSTOMER C
JOIN ORDERS O ON O.Customer_ID = C.Customer_ID
JOIN
(SELECT Customer_ID, OrderDate
FROM ORDERS
GROUP BY Customer_ID, OrderDate
HAVING COUNT(*) > 1) SRC
ON SRC.Customer_ID = O.Customer_ID AND SRC.OrderDate = O.OrderDate
In the script above, the last query (a subquery) would only return results where a customer had more than one order in a given day. By joining that to your main query, you would effectively produce the result asked in the OP.
Edit 1:
Regarding your comment below, I really recommend just going over your datamodel, trying to understand what's happening here, and fixing it on your own. But there is an easy - albeit hardly optimal solution to this by just using your own script above. Note, while this is not disastrous performance-wise, it's obviously not the cleanest, most effective method either. But it should work:
;WITH CTE AS (SELECT ad.Name + ' ' + ad.Vorname AS Customer,
pa.Kunde AS CustomerNr,
CONVERT(VARCHAR(10),p.datum,126) AS [Date],
(SELECT a.name + ' ' + a.Vorname AS Name FROM PRO_Mitarbeiter m LEFT JOIN ADR_Adressen a ON a.AdressNrADR=m.AdressNrADR WHERE m.MitNrPRO = l.MitNrPRO) as Employee,
p.Artikel_1 AS Article,
l.AufgabenNrCRM AS OrderNr
FROM ZUS_Therapie_Positionen p
INNER JOIN CRM_AufgabenLink l ON l.AufgabenNrCRM = p.Id_Aktivitaet
INNER JOIN CRM_Aufgaben ab ON ab.AufgabenNrCRM = p.Id_Aktivitaet
INNER JOIN PRO_Auftraege pa ON pa.AuftragNrPRO = ab.AuftragNrPRO
INNER JOIN ADR_Adressen ad ON ad.AdressNrADR = pa.Kunde
INNER JOIN ADR_GruppenLink gl ON gl.AdressNrADR = ad.AdressNrADR
INNER JOIN ADR_Gruppen g ON g.GruppeADR = gl.GruppeADR
WHERE l.MitNrPRO != 0
GROUP BY l.AufgabenNrCRM,ad.Name,ad.Vorname,pa.Kunde,p.datum,p.Artikel_1,l.MitNrPRO
ORDER BY pa.Kunde,p.datum,l.AufgabenNrCRM)
SELECT C.*
FROM CTE C
JOIN (Select CustomerNr, [Date]
FROM CTE B
GROUP BY CustomerNr, [Date]
HAVING COUNT(*) > 1) SRC
ON SRC.CustomerNr = C.CustomerNr AND SRC.[Date] = C.[Date]
This should work directly. But as I said, this is an ugly workaround where we're basically all but fetching the whole set twice, as opposed to just limiting the sub query to just the bare minimum of necessary tables. Your choice. :)
Tried that also and it didnt work. I also made a new query trying to Keep it so simple as possible and it doesnt work either. It still give me Single values back..
SELECT p.Datum,a.AufgabenNrCRM,auf.Kunde FROM CRM_Aufgaben a
LEFT JOIN ZUS_Therapie_Positionen p ON p.Id_Aktivitaet = a.AufgabenNrCRM
LEFT JOIN PRO_Auftraege auf ON auf.AuftragNrPRO = a.AuftragNrPRO
LEFT JOIN
(SELECT pa.Datum,au.Kunde FROM CRM_Aufgaben aa
LEFT JOIN ZUS_Therapie_Positionen pa ON pa.Id_Aktivitaet = aa.AufgabenNrCRM
LEFT JOIN PRO_Auftraege au ON au.AuftragNrPRO = aa.AuftragNrPRO
GROUP BY pa.Datum,au.Kunde
HAVING COUNT(*) > 1) SRC
ON SRC.Kunde = auf.Kunde
WHERE p.datum IS NOT NULL
GROUP BY p.Datum,a.AufgabenNrCRM,auf.Kunde
ORDER BY auf.Kunde,p.Datum

Duplicate Results with LISTAGG Function

I do see there are solutions for a similar question but I was unable to get them to work in my scenario.
I am returning duplicate codes while using the LISTAGG function.
Returning now:
SELECT
,CD.CLAIM
,CD.CLAIMLN
,CD.PROV_INVOICE_UNTS
,CD.APPR_UNTS
,CD.PROV_INVOICE_AMT
,CD.PROV_CNTRCT_AMT
,CD.PLAN_CNTRCT_AMT as PLAN_AMT
,LISTAGG(DX.DIAG_CD,', ') WITHIN GROUP (ORDER BY DX.LVL_CD) AS DX_CODES
FROM CLAIM_DETAIL CD
INNER JOIN PATIENT_INTAKE_PLAN PIP
ON CD.PAT_NBR = PIP.PAT_NBR AND CD.ITK_ID = PIP.ITK_ID
INNER JOIN HEALTH_PLAN HP
ON HP.PLAN_ID = PIP.PLAN_ID
INNER JOIN PROVIDER_CCXPORTAL PR
ON PR.PROV_ID = CD.PROV_ID
INNER JOIN PROVIDER_PARENT PRP
ON PR.PROV_PRNT_ID = PRP.PROV_PRNT_ID
INNER JOIN PATIENT_CCXPORTAL PTP
ON PTP.PAT_NBR = CD.PAT_NBR
INNER JOIN CLAIM C
ON C.CLM_ID = CD.CLM_ID
LEFT JOIN CLAIM_DIAGNOSIS DX
ON CD.CLM_ID = DX.CLM_ID
WHERE
C.RCPT_DT >= '01-JUL-2014'
I need it to return:
Use a regex to get rid of the duplicates
....as PLAN_AMT,
RTRIM(
REGEXP_REPLACE(
(listagg(DX.DIAG_CD,',') WITHIN GROUP (ORDER BY DX.LVL_CD) ),
'([^,]*)(,\1)+($|,)',
'\1\3'),
',') AS DX_CODES
FROM......
If there are very many DX_CODES per claim, your may string exceed the max length for a SQL varchar2.
Can you try this instead?
SELECT
,CD.CLAIM
,CD.CLAIMLN
,CD.PROV_INVOICE_UNTS
,CD.APPR_UNTS
,CD.PROV_INVOICE_AMT
,CD.PROV_CNTRCT_AMT
,CD.PLAN_CNTRCT_AMT as PLAN_AMT
, (SELECT listagg(dx.diag_cd,',') within group ( order by dx.lvl_cd, dx.diag_cd ) FROM ( SELECT distinct clm_id, lvl_cd, diag_cd FROM claim_diagnosis ) dx WHERE dx.clm_id = cd.clm_id ) dx_codes
--,LISTAGG(DX.DIAG_CD,', ') WITHIN GROUP (ORDER BY DX.LVL_CD) AS DX_CODES
FROM CLAIM_DETAIL CD
INNER JOIN PATIENT_INTAKE_PLAN PIP
ON CD.PAT_NBR = PIP.PAT_NBR AND CD.ITK_ID = PIP.ITK_ID
INNER JOIN HEALTH_PLAN HP
ON HP.PLAN_ID = PIP.PLAN_ID
INNER JOIN PROVIDER_CCXPORTAL PR
ON PR.PROV_ID = CD.PROV_ID
INNER JOIN PROVIDER_PARENT PRP
ON PR.PROV_PRNT_ID = PRP.PROV_PRNT_ID
INNER JOIN PATIENT_CCXPORTAL PTP
ON PTP.PAT_NBR = CD.PAT_NBR
INNER JOIN CLAIM C
ON C.CLM_ID = CD.CLM_ID
--LEFT JOIN CLAIM_DIAGNOSIS DX
--ON CD.CLM_ID = DX.CLM_ID
WHERE
C.RCPT_DT >= '01-JUL-2014'
Make sure there is an index on CLAIM_DIAGNOSIS.CLM_ID.

Vertical Join in an SQL Statement

I've got the following SQL Statement:
select * from Leaves inner join LeaveDetails on Leaves.LeaveId= LeaveDetails.LeaveId
inner join Employee on Leaves.EmployeeCode = Employee.EmployeeCode
inner join LeaveType on Leaves.LeaveTypeId= LeaveType.LeaveTypeId
inner join LeaveStatus on Leaves.StatusId = LeaveStatus.StatusId
inner join Employee_organizationaldetails on Employee_organizationaldetails.EmployeeCode=Employee.EmployeeCode
where Leaves.LeaveId = 7295
Employee_organizationdetails contains another column called reporting officer which is a foreign key to the same Employee table. Now I need to get the name of the Employee.
How can I write the above query so that I can get the name of the reporting officer as another column without fetching executing the query
select (FirstName + ' ' + LastName) as name from Employee where EmployeeCode = ReportingTo
Here ReportingTo is the employee code. I need to join them vertically. Something similar to Union operator
You want to join back to another "copy" of the Employee table:
select *, (ro.FirstName + ' ' + LastName) as ReportingName
from Leaves inner join LeaveDetails on Leaves.LeaveId= LeaveDetails.LeaveId
inner join Employee on Leaves.EmployeeCode = Employee.EmployeeCode
inner join LeaveType on Leaves.LeaveTypeId= LeaveType.LeaveTypeId
inner join LeaveStatus on Leaves.StatusId = LeaveStatus.StatusId
inner join Employee_organizationaldetails on Employee_organizationaldetails.EmployeeCode=Employee.EmployeeCode left outer join
Employee ro
on ro.EmployeeCode = ReportingTo
where Leaves.LeaveId = 7295;
You probably don't want the * -- I assume it is just a shorthand for the question. It is better to list columns explicitly, especially because there are duplicate column names.
Possible this be helpful for you -
SELECT
*
, ReportingName = ro.FirstName + ' ' + LastName
FROM (
SELECT *
FROM dbo.Leaves l
WHERE l.LeaveId = 7295
) l
JOIN dbo.LeaveDetails ld ON l.LeaveId = ld.LeaveId
JOIN dbo.Employee e ON l.EmployeeCode = e.EmployeeCode
JOIN dbo.LeaveType lt ON l.LeaveTypeId = lt.LeaveTypeId
JOIN dbo.LeaveStatus ls ON l.StatusId = ls.StatusId
JOIN dbo.Employee_organizationaldetails e2 ON e2.EmployeeCode = e.EmployeeCode
LEFT JOIN dbo.Employee ro ON ro.EmployeeCode = ReportingTo