Related
I have a query that has 2 data sets that I have union'd together. I have done a group by on each data Set as I am working with 2 different product types that are in two different tables but have the same data columns in each.
I want to group the data set as a whole and nothing I try seems to be working.
Here below is the code I have so far
(SELECT Distinct
max(Incep) as Startdate,
q1.Client,
max(q1.Ref) as Reference,
Max(Title) as Title,
Max(Forename)as Firstname,
Max(Surname) as Lastname,
max(Addr1) as Line1,
Max(Addr2)as line2,
max(Addr3) as line3,
MAX(addr4) as Line4,
Max(a1.Postcode) as Postcode,
max(Abode) as Abodetype,
Max(Phone) as Phone,
Max(fax) as Faxnumber,
max(Field1) as Marketing,
Max(a1.Age) as Ageofclient,
Max(Test)Passeddate,
max(Resdate) as residencydate,
Max(Occup) as Occupation,
max(EOccup) as industry,
Max(RESTR) as DriverRestrictions,
Max(Cover) As Covertype,
MAx(BONUS) As NCBYears,
Max([USE]) as Classofuse,
max(REG) as VehicleReg,
max(ABI) as VehicleABI,
Max(BOUGHT) as PurchasedDate,
max(Seats) as VehicleSeats,
MAX(a2.YEAR) as Yearofmake,
Max(garage) as Overnightlocation
FROM Quotes q1
left join agents QZ on QZ.CDLCode =q1.Op collate SQL_Latin1_General_CP1_CI_AS
left join MIS_O_C a1 on a1.Client = q1.client
left join MIS_O_PPC a2 on a2.Client = q1.client and a2.Ref = Q1.Ref
WHERE EDate > GETDATE()-180
and reportgroup not in ('Renewals', 'Underwriting', 'Exclude')
and Occup not in ('Delivery Courier','Courier')
and Field1 = 'CROSS'
and SEATS > '8'
and [USE] not in ('3')
and Source in ('DIREC', '1A984', '1A997','1A982', '1A998')
and Ptype = 'PC'
GROUP BY q1.Client
UNION ALL
SELECT Distinct
max(Incep) as Startdate,
q1.Client,
max(q1.Ref) as Reference,
Max(Title) as Title,
Max(Forename)as Firstname,
Max(Surname) as Lastname,
max(Addr1) as Line1,
Max(Addr2)as line2,
max(Addr3) as line3,
MAX(addr4) as Line4,
Max(a1.Postcode) as Postcode,
max(Abode) as Abodetype,
Max(Phone) as Phone,
Max(fax) as Faxnumber,
max(Field1) as Marketing,
Max(a1.Age) as Ageofclient,
Max(Test)Passeddate,
max(Resdate) as residencydate,
Max(Occup) as Occupation,
max(EOccup) as industry,
Max(RESTR) as DriverRestrictions,
Max(Cover) As Covertype,
MAx(BONUS) As NCBYears,
Max([USE]) as Classofuse,
max(REG) as VehicleReg,
max(ABI) as VehicleABI,
Max(BOUGHT) as PurchasedDate,
max(Seats) as VehicleSeats,
MAX(a2.YEAR) as Yearofmake,
Max(garage) as Overnightlocation
FROM Quotes q1
left join agents QZ on QZ.CDLCode =q1.Op collate SQL_Latin1_General_CP1_CI_AS
left join MIS_O_C a1 on a1.Client = q1.client
left join MIS_O_PGV a2 on a2.Client = q1.client
and a2.Ref = Q1.Ref
WHERE EDate > GETDATE()-180
and reportgroup not in ('Renewals', 'Underwriting', 'Exclude')
and Occup not in ('Delivery Courier','Courier')
and Field1 = 'CROSS'
and SEATS > '8'
and [USE] not in ('3')
and Source in ('DIREC', '1A984', '1A997','1A982', '1A998')
and Ptype = 'GV'
GROUP BY q1.Client)
How do I group the two data sets as a whole?
If you use your script as a subquery and GROUP BY outside then it will work;
SELECT FieldNames
FROM
( SELECT FieldNames
FROM Table1
GROUP BY FieldNames
UNION
SELECT FieldNames
FROM Table2
GROUP BY FieldNames
) a
GROUP BY FieldNames
Use the UNION ALL only for your product tables, not for all the query
Select Distinct max(Incep) as Startdate, q1.Client, max(q1.Ref) as Reference, Max(Title) as Title,Max(Forename)as Firstname, Max(Surname) as Lastname, max(Addr1) as Line1, Max(Addr2)as line2, max(Addr3) as line3, MAX(addr4) as Line4,Max(a1.Postcode) as Postcode, max(Abode) as Abodetype, Max(Phone) as Phone, Max(fax) as Faxnumber, max(Field1) as Marketing,
Max(a1.Age) as Ageofclient, Max(Test)Passeddate, max(Resdate) as residencydate, Max(Occup) as Occupation, max(EOccup) as industry, Max(RESTR) as DriverRestrictions, Max(Cover) As Covertype, MAx(BONUS) As NCBYears, Max([USE]) as Classofuse, max(REG) as VehicleReg, max(ABI) as VehicleABI, Max(BOUGHT) as PurchasedDate, max(Seats) as VehicleSeats, MAX(a2.YEAR) as Yearofmake, Max(garage) as Overnightlocation from Quotes q1
left join agents QZ on QZ.CDLCode =q1.Op collate SQL_Latin1_General_CP1_CI_AS
left join MIS_O_C a1 on a1.Client = q1.client
left join (
SELECT * FROM MIS_O_PPC WHERE Ptype = 'PC'
WHERE
UNION ALL
SELECT * FROM MIS_O_PGV WHERE Ptype = 'GV'
) a2 on a2.Client = q1.client and a2.Ref = Q1.Ref
where EDate > GETDATE()-180
and reportgroup not in ('Renewals', 'Underwriting', 'Exclude')
and Occup not in ('Delivery Courier','Courier')
and Field1 = 'CROSS'
and SEATS > '8'
and [USE] not in ('3')
and Source in ('DIREC', '1A984', '1A997','1A982', '1A998')
Group by q1.Client
Can someone show me how i would add to this CTE to include the column 'Address Type ' that is stored in another table called 'WeccoPartyAddress'?
I am trying to find duplicates for the first and last name, and mailing address where Address Type address = 'Mailing'
with dups as (
select
wp.GtId
from CORE.WeccoParty wp
where exists (select 1
from CORE.WeccoParty wpe
where wp.FirstName = wpe.FirstName
and wp.LastName = wpe.LastName
and wp.Dob = wpe.Dob
and wp.GtId <> wpe.GtId
)
)
select distinct
wp.GtId,
wp.CrmPartyId,
wp.LegalName,
wp.BusinessClass,
wp.RmFullName,
wp.PbeFullName,
wp.OverallClientStatus,
wp.OverallRpStatus,
wp.FirstName + ' ' + wp.LastName FullName,
wp.Dob
from CORE.WeccoParty wp
join dups d on d.GtId = wp.GtId
order by 9,1
Consider extending your CTE by adding a JOIN clause in outer and subquery to the WeccoPartyAddress table with needed WHERE clauses. Notice too the distinct added to avoid repeated IDs for possible one-to-many relationship between the tables.
with dups as (
select distinct p.GtId
from CORE.WeccoParty p
join CORE.WeccoPartyAddress a ON p.GtId = a.GtId
where exists (select 1
from CORE.WeccoParty sub_p
left join CORE.WeccoPartyAddress sub_a
on sub_p.GtId = sub_a.GtId and sub_a.AddressType = 'Mailing'
where (p.FirstName = sub_p.FirstName
and p.LastName = sub_p.LastName
and p.Dob = sub_p.Dob
and p.GtId <> sub_p.GtId)
and a.MailingAddress = sub_a.MailingAddress
and a.GtId <> sub_a.GtId
)
)
And depending on data and relationships (e.g., can GtId have same bio details AND/OR same mailing address?) which you would know more, you may need to adjust above query. These may involve swapping left join to join and/or the WHERE conditions such as:
where (p.FirstName = sub_p.FirstName
and p.LastName = sub_p.LastName
and p.Dob = sub_p.Dob
and p.GtId <> sub_p.GtId)
or
(a.MailingAddress = sub_a.MailingAddress
and a.GtId <> sub_a.GtId)
I'm using SQL Server 2016. I have a select-statement with a CASE. This CASE gives back a country-code. In the same select-statement I would like to query another table to retrieve the description which goes with this country-code. In order to do so I have created a subquery. In this subquery I want to use the result of the case in the where-clause.
SELECT
DelAddrCode
, CASE WHEN DelAddrCode = '0' THEN (SELECT Customeraddress.countrycode FROM Customeraddress WHERE Customeraddress.CustID = Salesorder.CustID)
ELSE (SELECT Deliveryaddress.countrycode FROM Deliveryaddress where Deliveryaddress.CustID = Salesorder.CustID AND Deliveryaddress.DelAddrCode = Salesorder.DelAddrCode)
END AS delivery_country
, (SELECT country.description from Country WHERE Country.countrycode = delivery_country)
FROM Salesorder
The logic here is that you have a default customer address, for instance in the US, but you can deliver a sales order on a different address like the UK. So first I retrieve the DelAddrCode. If 0 then I retrieve the countrycode from the CustomerAdress table. If not 0, then I will get the countrycode from the Deliveryaddress table.
Now that I have the countrycode I would like to get the country description from the Country table. I use a subquery for this. But the where-clause of this subquery depends on the result of the CASE. The above query gives an error: "Invalid column name 'del_country'".
The solution I found is to copy past the case and put it in the subquery:
SELECT
DelAddrCode
, CASE WHEN DelAddrCode = '0' THEN (SELECT Customeraddress.countrycode FROM Customeraddress WHERE Customeraddress.CustID = Salesorder.CustID)
ELSE (SELECT Deliveryaddress.countrycode FROM Deliveryaddress where Deliveryaddress.CustID = Salesorder.CustID AND Deliveryaddress.DelAddrCode = Salesorder.DelAddrCode)
END AS delivery_country
, (SELECT country.description from Country WHERE Country.countrycode =
(CASE WHEN DelAddrCode = '0' THEN (SELECT Customeraddress.countrycode FROM Customeraddress WHERE Customeraddress.CustID = Salesorder.CustID)
ELSE (SELECT Deliveryaddress.countrycode FROM Deliveryaddress WHERE Deliveryaddress.CustID = Salesorder.CustID and Deliveryaddress.DelAddrCode = Salesorder.DelAddrCode)
END))
FROM Salesorder
This gives me the result I want, but it makes the code a mess. Is there a way I can refer to the result of the CASE in the subquery to get the same result without having to copy-paste the same CASE again?
Thanks in advance!
Try the following code. It contains the CASE just once and I find it more readable.
SELECT t.delAddrCode,
country.description
FROM
(
SELECT Salesorder.DelAddrCode,
CASE
WHEN Salesorder.DelAddrCode = '0' THEN Customeraddress.countrycode
ELSE Deliveryaddress.countrycode
END AS delivery_country
FROM Salesorder
LEFT JOIN Customeraddress ON Customeraddress.CustID = Salesorder.CustID
LEFT JOIN Deliveryaddress ON Deliveryaddress.CustID = Salesorder.CustID
AND Deliveryaddress.DelAddrCode = Salesorder.DelAddrCode
) t
LEFT JOIN Country ON country.countrycode = t.delivery_country;
Outer join the address tables and see which one matches with COALESCE:
SELECT
DelAddrCode,
COALESCE(ca.countrycode, da.countrycode) AS countrycode,
c.description
FROM Salesorder so
LEFT JOIN Customeraddress ca ON ca.CustID = so.CustID AND so.DelAddrCode = 0
LEFT JOIN Deliveryaddress da ON da.CustID = so.CustID AND da.DelAddrCode = so.DelAddrCode
JOIN country c ON c.countrycode = COALESCE(ca.countrycode, da.countrycode);
If Deliveryaddress.DelAddrCode cannot be 0 (which I assume), you can even make this
JOIN country c ON c.countrycode IN (ca.countrycode, da.countrycode);
which may lead to a better execution plan for being a simpler link.
I have two tables th_Therapy_Note and th_Approved. When a note in th_Therapy_Note gets approved, the application inserts a record to th_Approved.
A note can get rejected for several reasons after it has been approved (don't ask me why, as I did not design this app, lol). So if a note is rejected after being approved, another entry to th_Approved is inserted.
th_Approved.th_approved_isApproved is a boolean (bit) column, so depending on the status, the note entry in this table for this column in true or false
So multiple lines for the same note can exist in th_Approved with different th_Approved.th_approved_isApproved status, the last entry being the most recent one and correct status
The main purpose for the below query is to select notes that are ready to be 'finalized'. The issue with the below query is in the last inner join filter 'AND th_Approved.th_approved_isApproved = 1' This is selecting notes that effectively have been approved, meaning they should have an entry in th_Approved and th_Approved.th_approved_isApproved is true.
This works perfect for notes with single entries in th_Approved, but notes with multiple entries in th_Approved (as explained above) represent an issue if the last entry for that particular note is false. The query will still pick it up because there is at least one entry with th_Approved.th_approved_isApproved as true, even when last correct status is false. I need to only look at this last entry to be able to determine the correct status for a note and select it or not depending on the status.
Last part of the query (and th_Therapy_Note.th_note_id=16239) is just for my testing as this note has multiple entries, but the final will not have this.
How can I solve my issue? I have been looking at several strategies with no luck.....Hopefully I made sense :) thanks
SELECT Distinct Convert(varchar,th_Therapy_Note.th_note_id) as NOTEID, '054' as PROGCODE, Rtrim(ch.child_caseNumber) as CASEID,
Case th_TherapyType.shortname when 'ST' then 'SP' else rtrim(th_TherapyType.shortname) end as SERVTYPE, Convert(varchar,th_Therapy_Note.th_note_dateofservice,101) as DELSERVDATE,
Cast(((Select sum(th_TherapyServiceProvided.units) From th_TherapyServiceProvided where th_DirectServices.th_ds_id = th_TherapyServiceProvided.th_ds_id)/60) as varchar) as SERVHRS,
Cast(((Select sum(th_TherapyServiceProvided.units) From th_TherapyServiceProvided where th_DirectServices.th_ds_id = th_TherapyServiceProvided.th_ds_id)%60) as varchar) as SERVMIN,
'1' as METHOD, isnull(th_Users.trad_id, ' ') as SPROVNUM, th_Users.th_user_lname, '' as COVISIT
FROM th_Therapy_Note INNER JOIN
child_tbl AS ch ON th_Therapy_Note.child_id = ch.child_recordId INNER JOIN
th_DirectServices ON th_Therapy_Note.th_note_id = th_DirectServices.th_note_id INNER JOIN
LookUp_contactType ON th_Therapy_Note.contact_type_id = LookUp_contactType.recId INNER JOIN
th_Users ON th_Therapy_Note.service_coordinator = th_Users.th_user_email INNER JOIN
th_TherapyType ON th_Therapy_Note.therapy_type = th_TherapyType.id INNER JOIN
th_Approved ON th_Therapy_Note.th_note_id = th_Approved.th_note_id AND th_Approved.th_approved_isApproved = 1
WHERE (ch.child_recordId =
(SELECT MAX(child_recordId) AS Expr1
FROM child_tbl
WHERE (child_caseNumber = ch.child_caseNumber)))
and th_Therapy_Note.th_note_dateofservice > '4/22/2014' and th_Therapy_Note.th_note_id=16239
You can use a "MAX" trick (or "MIN" or similar). On a date or unique column is typical.
Here is a generic Northwind example that uses the MAX(OrderDate) (where a customer has more than one order).
The logic below falls apart if there are 2 orders with the same order-date, and those dates are the "max" date. So a unique identifier that is orderable is preferred)
Use Northwind
GO
Select cust.* , ords.*
from dbo.Customers cust
LEFT OUTER JOIN dbo.Orders ords
ON
(
ords.CustomerID = cust.CustomerID
AND ords.OrderDate =
(SELECT MAX(OrderDate)
FROM dbo.Orders innerords
WHERE innerords.CustomerID = cust.CustomerID
)
)
where cust.CustomerID = 'ALFKI'
Since you have a sequential ID on th_Approved, then I'd use that. Integer comparison on id is perfect. Date/Datetime comparison can sometimes add problems.
So I'd try this:
SELECT Distinct
Convert(varchar,th_Therapy_Note.th_note_id) as NOTEID,
'054' as PROGCODE,
Rtrim(ch.child_caseNumber) as CASEID,
Case th_TherapyType.shortname
when 'ST' then 'SP'
else rtrim(th_TherapyType.shortname)
end as SERVTYPE,
Convert(varchar,th_Therapy_Note.th_note_dateofservice,101) as DELSERVDATE,
Cast(((
Select sum(th_TherapyServiceProvided.units)
From th_TherapyServiceProvided
where th_DirectServices.th_ds_id = th_TherapyServiceProvided.th_ds_id)/60) as varchar
) as SERVHRS,
Cast(((
Select sum(th_TherapyServiceProvided.units)
From th_TherapyServiceProvided
where th_DirectServices.th_ds_id = th_TherapyServiceProvided.th_ds_id)%60) as varchar
) as SERVMIN,
'1' as METHOD,
isnull(th_Users.trad_id, ' ') as SPROVNUM,
th_Users.th_user_lname, '' as COVISIT
FROM th_Therapy_Note
INNER JOIN child_tbl AS ch ON th_Therapy_Note.child_id = ch.child_recordId
INNER JOIN th_DirectServices ON th_Therapy_Note.th_note_id = th_DirectServices.th_note_id INNER JOIN LookUp_contactType ON th_Therapy_Note.contact_type_id = LookUp_contactType.recId INNER JOIN th_Users ON th_Therapy_Note.service_coordinator = th_Users.th_user_email
INNER JOIN th_TherapyType ON th_Therapy_Note.therapy_type = th_TherapyType.id
INNER JOIN th_Approved ON th_Approved.th_approved_id=(
SELECT MAX(th_approved_id)
FROM th_Approved
WHERE th_Therapy_Note.th_note_id = th_Approved.th_note_id)
WHERE ch.child_recordId = (
SELECT MAX(child_recordId)
FROM child_tbl
WHERE child_caseNumber = ch.child_caseNumber)
AND th_Therapy_Note.th_note_dateofservice > '4/22/2014'
AND th_Approved.th_approved_isApproved = 1
AND th_Therapy_Note.th_note_id=16239
Without access to your dataset to test this with this is the best I can give you.
In essence what I am doing is filtering out the duplicates using a CTE and the TSQL command ROW NUMBER using whatever date function you have. then placing the filtered out list into your main query.
;with fixDuplicateCTE(
SELECT m.th_note_id, m.tag
FROM ( SELECT TH_NOTE_ID ROW_NUMBER OVER(partition by th_note_id ORDER BY [SOME DATE FUNCTION YOU HAVE!!!!!] desc) as tag FROM th_approved) as m
INNER JOIN th_approved AS a on m.th_note_id = a.th_note_id
WHERE m.tag = 1
)
SELECT Distinct Convert(varchar,th_Therapy_Note.th_note_id) as NOTEID, '054' as PROGCODE, Rtrim(ch.child_caseNumber) as CASEID,
Case th_TherapyType.shortname
when 'ST' then 'SP' else rtrim(th_TherapyType.shortname) end as SERVTYPE, Convert(varchar,th_Therapy_Note.th_note_dateofservice,101) as DELSERVDATE,
Cast(((Select sum(th_TherapyServiceProvided.units) From th_TherapyServiceProvided where th_DirectServices.th_ds_id = th_TherapyServiceProvided.th_ds_id)/60) as varchar) as SERVHRS,
Cast(((Select sum(th_TherapyServiceProvided.units) From th_TherapyServiceProvided where th_DirectServices.th_ds_id = th_TherapyServiceProvided.th_ds_id)%60) as varchar) as SERVMIN,
'1' as METHOD, isnull(th_Users.trad_id, ' ') as SPROVNUM, th_Users.th_user_lname, '' as COVISIT
FROM th_Therapy_Note
INNER JOIN child_tbl AS ch ON th_Therapy_Note.child_id = ch.child_recordId
INNER JOIN th_DirectServices ON th_Therapy_Note.th_note_id = th_DirectServices.th_note_id
INNER JOIN LookUp_contactType ON th_Therapy_Note.contact_type_id = LookUp_contactType.recId
INNER JOIN th_Users ON th_Therapy_Note.service_coordinator = th_Users.th_user_email
INNER JOIN th_TherapyType ON th_Therapy_Note.therapy_type = th_TherapyType.id
INNER JOIN fixDuplicateCTE ON th_Therapy_Note.th_note_id = th_Approved.th_note_id AND th_Approved.th_approved_isApproved = 1
WHERE (ch.child_recordId =
(SELECT MAX(child_recordId) AS Expr1
FROM child_tbl
WHERE (child_caseNumber = ch.child_caseNumber)))
and th_Therapy_Note.th_note_dateofservice > '4/22/2014' and th_Therapy_Note.th_note_id=16239
The following MS Access 2010 query only outputs values for FirstName, HomePhone, and ClientNumber. It is not outputting any values for LastName.
Can anyone show me how to change it so that it outputs values for LastName also?
SELECT
ActiveCustomers.FirstName
, ActiveCustomers.LastName
, tblClientAddress.HomePhone
, ActiveCustomers.ClientNumber
FROM (
SELECT
Clients.ClientNumber
, Clients.FirstName
, Clients.LastName (
SELECT COUNT(ReferralDate) FROM IntakeTable
WHERE Clients.ClientNumber = IntakeTable.ClientNumber
AND Len(ReferralDate & '') > 0
) AS IntakeCount
, (
SELECT COUNT(ExitDate)
FROM ExitTable
WHERE Clients.ClientNumber = ExitTable.ClientNumber
AND Len(ExitDate & '') > 0
) AS ExitCount
FROM Clients
) AS ActiveCustomers
INNER JOIN tblClientAddress
ON ActiveCustomers.ClientNumber = tblClientAddress.ClientNumber
WHERE ActiveCustomers.IntakeCount > [ExitCount]
AND tblClientAddress.CurrentResidence = True;
You appear to be missing a comma after Clients.LastName. Try:
SELECT ActiveCustomers.FirstName, ActiveCustomers.LastName, tblClientAddress.HomePhone, ActiveCustomers.ClientNumber
FROM
(SELECT Clients.ClientNumber,
Clients.FirstName,
Clients.LastName,
(SELECT COUNT(ReferralDate) FROM IntakeTable WHERE Clients.ClientNumber = IntakeTable.ClientNumber AND Len(ReferralDate & '') > 0) AS IntakeCount,
(SELECT COUNT(ExitDate) FROM ExitTable WHERE Clients.ClientNumber = ExitTable.ClientNumber AND Len(ExitDate & '') > 0) AS ExitCount
FROM Clients) AS ActiveCustomers
INNER JOIN tblClientAddress ON ActiveCustomers.ClientNumber = tblClientAddress.ClientNumber
WHERE (((ActiveCustomers.IntakeCount)>[ExitCount]) AND
((tblClientAddress.CurrentResidence)=True));
EDIT:
It seems likely that:
You have a many-to-one (or one-to-many) relationship between Clients and tblClientAddress, and you have two records on the "many" side. If you are getting duplicate records, you could add a DISTINCT or a GROUP BY,
And/Or:
That the (SELECT COUNT( subqueries are somehow messing up their parent query, and need to be modified so that they can go into their parent query's FROM clause with an Inner Join, e.g.:
(SELECT ClientNumber, COUNT(ReferralDate) as IntakeCount FROM IntakeTable WHERE Len(ReferralDate & '') > 0 GROUP BY ClientNumber) AS qryIntakeCount