SQL Nested select grouped with several rows of results - sql

Hope this makes sense..
I have the following database tabels.
I am trying to group a resultset together in an SQL statement.
This is my current SQL statements:
SELECT
Patient.ID,
Patient.Name,
AnimalType.Value as AnimalType,
Patient.Age,
Customer.Firstname,
Customer.Lastname
FROM Patient
INNER JOIN Customer ON Patient.Owner_FK = Customer.ID
INNER JOIN AnimalType ON Patient.Type_FK = AnimalType.ID
SELECT
Treatment.Treatment_Date,
TreatmentType.Type
FROM Treatment
INNER JOIN TreatmentItem ON Treatment.ID = TreatmentItem.Treatment_FK
INNER JOIN TreatmentType ON TreatmentItem.TreatmentType_FK = TreatmentType.ID
INNER JOIN Patient ON TreatmentItem.Patient_FK = Patient.ID
WHERE Patient.ID = 132
There are two issues with this,
I have a static ID, and the results are split.
This is result of the above SQL's
My Issue is that the last resultset, should be together with the corresponding "Animal (patient)".
But without duplicate data. I could get the data all in one go, but then i would have a lot of duplicate rows of data with only the TreatmentType being different..
So how do i make this work ?
I have searched to no avail, and have not been able to make a correct Group by, that would make it work.
Does it make any sense ?
Is it even possible ?
example of desired result:

I believe you can achieve what you want with a single query, CASE statements, and the ROW_NUMBER() function, but it would require conversions of all non-text columns.
Here is a rough stab at a potential solution (I did not build your DB, so I haven't verified that this exact SQL runs, but the overall concept works).
WITH CTE_PatientTreatments AS (
SELECT
-- Get the row number for each treatment for a given patient
ROW_NUMBER() OVER (PARTITION BY Patient.ID ORDER BY Treatment.ID) AS RowNum,
Patient.ID,
Patient.Name,
AnimalType.Value as AnimalType,
Patient.Age,
Customer.Firstname,
Customer.Lastname,
Treatment.Treatment_Date,
TreatmentType.Type
FROM Patient
INNER JOIN Customer ON Patient.Owner_FK = Customer.ID
INNER JOIN AnimalType ON Patient.Type_FK = AnimalType.ID
INNER JOIN TreatmentItem ON TreatmentItem.Patient_FK = Patient.ID
INNER JOIN Treatment ON Treatment.ID = TreatmentItem.Treatment_FK
INNER JOIN TreatmentType ON TreatmentItem.TreatmentType_FK = TreatmentType.ID
WHERE Patient.ID = 132
-- Ensure rows are sorted so that rows for the same patient are always together
ORDER BY Patient.ID, Treatment.ID
)
-- Only display patient information for the first row
SELECT -- Convert numeric columns to text so that the "ELSE ''" doesn't get coerced into a number (0)
CASE WHEN (RowNum > 1) THEN '' ELSE CAST(ID AS VARCHAR) END AS ID,
CASE WHEN (RowNum > 1) THEN '' ELSE Name END AS Name,
CASE WHEN (RowNum > 1) THEN '' ELSE AnimalType END AS AnimalType,
CASE WHEN (RowNum > 1) THEN '' ELSE CAST(Age AS VARCHAR) END AS Age,
CASE WHEN (RowNum > 1) THEN '' ELSE Firstname END AS Firstname,
CASE WHEN (RowNum > 1) THEN '' ELSE Lastname END AS Lastname,
Treatment_Date,
Type
FROM CTE_PatientTreatments

Related

JOIN AND CASE MORE AN TABLE

I have 2 tables; the first one ORG contains the following columns:
ORG_REF, ARB_REF, NAME, LEVEL, START_DATE
and the second one WORK contains these columns:
ARB_REF, WORK_STREET - WORK_NUM, WORK_ZIP
I want to do the following: write a select query that search in work and see if the WORK_STREET, WORK_ZIP are duplicate together, then you should look at WORK_NUM. If it is the same then output value ' ok ', but if WORK_NUM is not the same, output 'not ok'
I wrote this SQL query:
select
A.ARB_REF, A.WORK_STREET, A.WORK_NUM, A.WORK_ZIP
case when B.B = 1 then 'OK' else 'not ok' end
from
work A
join
(select
WORK_STREET, WORK_ZIP count(distinct , A.WORK_NUM) B
from
WORK
group by
WORK_STREET, WORK_ZIP) B on B.WORK_STREET = A.WORK_STREET
and B.WORK_ZIP = A.WORK_ZIP
Now I want to join the table ORG with this result I want to check if every address belong to org if it belong I should create a new column result and set it to yes in it (RESULT) AND show the "name" column otherwise set no in 'RESULT'.
Can anyone help me please?
While you can accomplish your result by adding a left outer join to the query you've already started, it might be easiest to just use count() over....
with org_data as (
-- do the inner join before the left join later
select * from org1 o1 inner join org2 o2 on o2.orgid = o1.orgid
)
select
*,
count(*) over (partition by WORK_STREET, WORKZIP) as cnt,
case when o.ARB_REF is not null then 'Yes' else 'No' end as result
from
WORK w left outer join org_data o on o.ARB_REF = w.ARB_REF

Conditional IN Statement to be used inside Postgres function

I am working on Postgres and I have two tables vehicles and vehicles_flag. There are no relations between the two tables and hence we can not join two tables to fetch the required data.
The table structure is below (vehicle_flag table may not contain all the id present in the vehicle table) :
[Table structure]
I am writing a function that will accept multiple input parameters. I have to select vehicle id from the vehicle_flag table only if the flag value is true: otherwise, I have to ignore the vehicel_flag table. My aim is to achieve something like this, but turns out the case statement expects scaler output:
select count(id) from vehicles
where
vehicles.id in (case
when #hasbluetooth =1 then (select distinct id from vehicle_flags where flag='bluetooth' and value = '1')
else
(select distinct id from vehicles)
end)
and
vehicles.id in (case
when #hasac =1 then (select distinct id from vehicle_flags where flag='ac' and value = '1')
else
(select distinct id from vehicles)
end)
Kindly suggest any solution to achieve this.
I suspect you want:
select v.*
from vehicle v
left join vehicle_flags vf on vf.id = v.id
group by v.id
having
(#hasbluetooth = 0 or bool_or(vf.flag = 'bluetooth' and vf.value = 1)
and (#hasac = 0 or bool_or(vf.flag = 'ac' and vf.value = 1)

Get Distinct values from one table in a join query containing column data type like ntext

I have two tables
Review and ProjectsReview. I want to change the order by columns without impacting the result. Initial order by was on createdDate column from review table.
Initial query is as below.
SELECT
*
FROM Review r
WHERE (status IS NULL
OR fstatus = '')
AND (crBy = '100'
OR crByPr = '')
ORDER BY createdDate
The query returns 8 rows.
The user wants to change the order by using program name which is in another table. The query to get the same is as below.
SELECT
r.*
FROM Review r
INNER JOIN ProjectsReview rp
ON rp.rID = r.rID
WHERE (status IS NULL
OR fstatus = '')
AND (crBy = '100'
OR crByPr = '')
ORDER BY prNo, prName
This returns 10 rows. But the required result is only 8 rows and only columns of review table.
I cannot apply group by on all the columns from Review table since there are data types with image and ntext.
Is there a way to achieve this without inserting the data to a temp table and get distinct values.
Try this
with cte
as
(
select
rn = row_number() over(partition by rID order by prNo,prName),
rID,
prNo,
prName
from ProjectsReview
)
SELECT r.*
FROM Review r
inner join cte rp on rp.rID =r.rID
WHERE (status IS NULL OR fstatus = '') AND (crBy = '100' OR crByPr = '')
and cte.rn = 1
ORDER BY prNo,prName

Selecting ONLY Duplicates from a joined tables query

I have the following query that I'm trying to join two tables matching their ID so I can get the duplicated values in "c.code". I've tried a lot of queries but nothing works. I have a 500k rows in my database and with this query I only get 5k back, which is not right. Im positive it's at least 200K. I also tried to use Excel but it's too much for it to handle.
Any ideas?
Thanks in advance, everyone.
SELECT c.code, c.name as SCT_Name, t.name as SYNONYM_Name, count(c.code)
FROM database.Terms as t
join database.dbo.Concepts as c on c.ConceptId = t.ConceptId
where t.TermTypeCode = 'SYNONYM' and t.ConceptTypeCode = 'NAME_Code' and c.retired = '0'
Group by c.code, c.name, t.name
HAVING COUNT(c.code) > = 1
Order by c.code
with data as (
select c.code, c.name as SCT_Name, t.name as SYNONYM_Name
from database.Terms as t inner join database.dbo.Concepts as c
on c.ConceptId = t.ConceptId
where
t.TermTypeCode = 'SYNONYM'
and t.ConceptTypeCode = 'NAME_Code'
and c.retired = '0'
)
select *
--, (select count(*) from data as d2 where d2.code = data.code) as code_count
--, count(*) over (partition by code) as code_count
from data
where code in (select code from data group by code having count(*) > 1)
order by code
If you want just duplicates of c.code, your Group By is wrong (and so is your Having clause). Try this:
SELECT c.code
FROM database.Terms as t
join database.dbo.Concepts as c on c.ConceptId = t.ConceptId
where t.TermTypeCode = 'SYNONYM' and t.ConceptTypeCode = 'NAME_Code' and c.retired = '0'
Group by c.code
HAVING COUNT(c.code) > 1
This will return all rows where you have more than one c.code value.
You need to use INTERSECT instead of JOIN. Basically you perform the select on the first table then intersect with the second table. The result is the duplicate rows.
Only select the id column, though, otherwise the intersect won't work as expected.

Display Y/N column if record found in detail table

I'm trying to create a query so that I can have a column show Y/N if a particular item was ordered for a group of orders. The item I'm looking for would be OLI.id = '538'.
So my results would be:
Order#, Customer#, FreightPaid
12345, 00112233, Y
12346, 00112233, N
I cannot figure out if I need to use a subquery or the where exists function ?
Here's my current query:
SELECT distinct
OrderID,
Accountuid as Customerno
FROM [SMILEWEB_live].[dbo].[OrderLog] OL
inner join Orderlog_item OLI on OLI.orderlogkey = OL.[key]
inner join Account A on A.uid = OL.Accountuid
where A.GroupId = 'X9955'
and OL.CreateDate >= GETDATE() - 60
I would suggest an exists clause instead of a join:
select ol.OrderID, ol.Accountuid as Customerno,
(case when exists (select 1
from Orderlog_item OLI join
Account A
on A.uid = OL.Accountuid
where OLI.orderlogkey = OL.[key] and A.GroupId = 'X9955'
)
then 1 else 0
end) as flag
from [SMILEWEB_live].[dbo].[OrderLog] OL
where OL.CreateDate >= GETDATE() - 60;
This prevents a couple of problems. First, duplicate rows which are caused when there are multiple matching rows (and select distinct add unnecessary overhead). Second, missing rows, which happen when you use inner join instead of an outer join.