Trouble Aggregating Rows with SQL Statement - sql

I am attempting to pivot some data out of the Vendor column in this table, creating new columns for each of my vendors. Ideally, I would have 1 row for each ContractDate, and then 2 values. However, I'm ending up with 2 rows of a distinct ContractDate.
I believe i may need some sort of temp table query to do this...i'm not sure though.
SELECT [ContractDate],
CASE WHEN Vendor = 'AirDat'
THEN (sum(wf.Temppop) / sum(wf.Population)) END as 'AirDat',
CASE WHEN Vendor = 'CWG'
THEN (sum(wf.Temppop) / sum(wf.Population)) END as 'CWG'
FROM [ECPDB].[dbo].[weather.forecast] as wf
INNER JOIN ecpdb.[lookup].[newWeatherStation] as ws
ON wf.[Station_ID] = ws.[Station ID]
INNER JOIN ecpdb.[lookup].[CountyNew] as c
ON ws.[County FIPS] = c.[County FIPS]
WHERE tradedate = '7/2/2012'
AND [BENTEK Cell] = 'Northeast'
GROUP BY [ContractDate], vendor

You can do this using a subquery;
Select ContractDate,
max(case when Vendor = 'AirDat' THEN Vendor_Average End) as AirDAT,
max(case when Vendor = 'CWG' THEN Vendor_Average End) as CWG
from (
SELECT [ContractDate] , Vendor, (sum(wf.Temppop) / sum(wf.Population)) as Vendor_Average
FROM [ECPDB].[dbo].[weather.forecast] as wf
inner join ecpdb.[lookup].[newWeatherStation] as ws
on wf.[Station_ID] = ws.[Station ID]
inner join ecpdb.[lookup].[CountyNew] as c
on ws.[County FIPS] = c.[County FIPS]
where tradedate = '7/2/2012' and [BENTEK Cell] = 'Northeast'
group by ContractDate, Vendor
) as Subquery
group by Contractdate
This way, the query runs and finds the values you need, and then you pick the rows you want without needing to group.

Related

SQL nested grouping issue

Here's my query:
select
cast(ar.AudienceCreationDate as date) as AudienceDate,
Count(*) as [Count],
count(case when ar.Source = 'Contact' then ar.Id end) as PatientCount,
count(case when ar.Source = 'PatientContact' then ar.Id end) as PatientContactCount,
(
select
count(*)
from
_SMSMessageTracking sms
inner join
[CTT Preferences] pref on pref.ContactId = sms.SubscriberKey
where
sms.Name <> 'ky_ctt_join' and pref.Source = 'Patient'
) as PatientSMS,
(
select
count(*)
from
_SMSMessageTracking sms
inner join
[CTT Preferences] pref on pref.ContactId = sms.SubscriberKey
where
sms.Name <> 'ky_ctt_join' and pref.Source = 'PatientContact'
) as PatientContactSMS
from
Daily_Symptom_Check_Audience_Archive ar
group by
cast(ar.AudienceCreationDate as date)
And here's the result set it creates:
The issue I'm having is that the values in the rightmost two columns are the same across the board, for all records. This number represents the TOTAL, and not aggregated by day, as the other values indicate. I realize that I'm doing something wrong - what can I do to modify my query to effectively have a proper "grouping" on these last two columns just like all the other data in this table?
in the where clause of the nested query add sms.AudienceDate = ar.AudienceDate

SQL: Split rows with same ID into columns + left join

I have a cs cart database and I am trying to select all the attributes for all the products, the problem is that for each separate attribute for a product, my query creates a new row, I want to to have a single row for each products that has all the attributes into columns.
This is my query right now:
SELECT a.product_id, b.variant, c.description, d.product_code
FROM cscart_product_features_values a
LEFT JOIN cscart_product_feature_variant_descriptions b ON a.variant_id = b.variant_id
LEFT JOIN cscart_product_features_descriptions c ON a.feature_id = c.feature_id
LEFT JOIN cscart_products d ON a.product_id = d.product_id
After I run the query, I get the following result:
product_id;"variant";"description";"product_code"
38;"1st";"Grade Level";"750"
38;"Math";"Subject Area";"750"
38;"Evan-Moor";"Publisher";"750"
etc next product
What I want is this:
product_id;"product_code";"Grade Level";"Subject Area";"Publisher"
38;"750";"1st";"Math";"Evan-Moor"
etc next product
We only have 3 type of attributes: Grade Level, Subject Area and Publisher.
Any ideas how to improve my query and achieve this? I would be happy even with concatenating all 3 attributes in one column, delimited by ",".
This is a generic SQL solution using GROUP BY and MAX(case expression) to achieve the transformation of 3 rows into a single row with the 3 columns.
SELECT
v.product_id
, p.product_code
, MAX(CASE WHEN fd.description = 'Grade Level' THEN vd.variant END) AS GradeLevel
, MAX(CASE WHEN fd.description = 'Subject Area' THEN vd.variant END) AS SubjectArea
, MAX(CASE WHEN fd.description = 'Publisher' THEN vd.variant END) AS Publisher
FROM cscart_products p
LEFT JOIN cscart_product_features_values v ON p.product_id = v.product_id
LEFT JOIN cscart_product_feature_variant_descriptions vd ON v.variant_id = vd.variant_id
LEFT JOIN cscart_product_features_descriptions fd ON v.feature_id = fd.feature_id
GROUP BY
v.product_id
, p.product_code
This approach should work on just about any SQL database.
Note also that I have changed the order of tables because I presume there has to be a row in cscart_products, but there might not be related rows in the other tables.
I have also changed the aliases, personally I do not care for aliaes based on the order of use in a query (e.g. I just changed the order so I had to change all references). I have use 'p' = product, 'v' = variant, 'vd' = variant description & 'fd' = feature description' - with such a convention for aliases I can re-arrange the query without changing every reference.

Only return value that matches the ID on table 1

I have tried all possible joins and sub-queries but I cant get the data to only return one value from table 2 that exactly matches the vendor ID. If I dont have the address included in the query, I get one hit for the vendor ID. How can I make it so that when I add the address, I only want the one vendor that I get prior to adding the address.
The vendor from table one must be VEN-CLASS IS NOT NULL.
This was my last attempt using subquery:
SELECT DISTINCT APVENMAST.VENDOR_GROUP,
APVENMAST.VENDOR,
APVENMAST.VENDOR_VNAME,
APVENMAST.VENDOR_CONTCT,
APVENMAST.TAX_ID,
Subquery.ADDR1
FROM (TEST.dbo.APVENMAST APVENMAST
INNER JOIN
(SELECT APVENADDR.ADDR1,
APVENADDR.VENDOR_GROUP,
APVENADDR.VENDOR,
APVENMAST.VEN_CLASS
FROM TEST.dbo.APVENADDR APVENADDR
INNER JOIN TEST.dbo.APVENMAST APVENMAST
ON (APVENADDR.VENDOR_GROUP = APVENMAST.VENDOR_GROUP)
AND (APVENADDR.VENDOR = APVENMAST.VENDOR)
WHERE (APVENMAST.VEN_CLASS IS NOT NULL)) Subquery
ON (APVENMAST.VENDOR_GROUP = Subquery.VENDOR_GROUP)
AND (APVENMAST.VENDOR = Subquery.VENDOR))
INNER JOIN TEST.dbo.APVENLOC APVENLOC
ON (APVENMAST.VENDOR_GROUP = APVENLOC.VENDOR_GROUP)
AND (APVENMAST.VENDOR = APVENLOC.VENDOR)
WHERE (APVENMAST.VEN_CLASS IS NOT NULL)
Try this:
SELECT APVENMAST.VENDOR_GROUP
, APVENMAST.VENDOR
, APVENMAST.VENDOR_VNAME
, APVENMAST.VENDOR_CONTCT
, APVENMAST.TAX_ID
, APVENADDR.ADDR1
FROM TEST.dbo.APVENMAST APVENMAST
INNER JOIN (
select VENDOR_GROUP, VENDOR, ADDR1
, row_number() over (partition by VENDOR_GROUP, VENDOR order by ADDR1) r
from TEST.dbo.APVENADDR
) APVENADDR
ON APVENADDR.VENDOR_GROUP = APVENMAST.VENDOR_GROUP
AND APVENADDR.VENDOR = APVENMAST.VENDOR
AND APVENADDR.r = 1
--do you need this table; you're not using it...
--INNER JOIN TEST.dbo.APVENLOC APVENLOC
--ON APVENMAST.VENDOR_GROUP = APVENLOC.VENDOR_GROUP
--AND APVENMAST.VENDOR = APVENLOC.VENDOR
WHERE APVENMAST.VEN_CLASS IS NOT NULL
--if the above inner join was to filter results, you can do this instead:
and exists (
select top 1 1
from TEST.dbo.APVENLOC APVENLOC
ON APVENMAST.VENDOR_GROUP = APVENLOC.VENDOR_GROUP
AND APVENMAST.VENDOR = APVENLOC.VENDOR
)
I found another column in the APVENLOC table that I can filter on to get the unique vendor. Turns out if the vendor address is for the main office, the vendor location is set blank.
Easier than I thought it would be!
SELECT DISTINCT APVENMAST.VENDOR_GROUP,
APVENMAST.VENDOR,
APVENMAST.VENDOR_VNAME,
APVENADDR.ADDR1,
APVENMAST.VENDOR_SNAME,
APVENADDR.LOCATION_CODE,
APVENMAST.VEN_CLASS
FROM TEST.dbo.APVENMAST APVENMAST
INNER JOIN TEST.dbo.APVENADDR APVENADDR
ON (APVENMAST.VENDOR_GROUP = APVENADDR.VENDOR_GROUP)
AND (APVENMAST.VENDOR = APVENADDR.VENDOR)
WHERE (APVENADDR.LOCATION_CODE = ' ')
Shaji

SQL attribute variant within the same statement

Having the following statement gives me 4 columns (location,description,parent,count) depending on the status:
SELECT
KINCIDENT.location, LOCATIONS.description,
LOCHIERARCHY.parent, count(KINCIDENT.incnum)
FROM
KINDICENT, LOCATIONS, LOCHIERARCHY
WHERE
KINCIDENT.location = LOCATIONS.location
and LOCATIONS.location = LOCHIERARCHY.location
AND KINCIDENT.status = 'ECCAPR'
GROUP BY
KINCIDENT.location, LOCATIONS.description, LOCHIERARCHY.parent
ORDER BY
parent;
However, I'd like a 5th column that gives me the count but when KINCIDENT.status='FSAPR' instead. How can I specify which status each count column takes?
You want conditional aggregation. You should also learn to use explicit joins:
SELECT k.location, l.description, h.parent,
SUM(CASE WHEN k.status = 'ECCAPR' THEN 1 ELSE 0 END) as cnt_ECCAPR,
SUM(CASE WHEN k.status = 'FSAPR' THEN 1 ELSE 0 END) as cnt_FSAPR
FROM KINDICENT k JOIN
LOCATIONS l
ON k.location = l.location JOIN
LOCHIERARCHY h
ON l.location = h.location
GROUP BY k.location, l.description, h.parent
ORDER BY parent;
I also introduced table aliases which generally make queries easier to write and to read.

Group on two columns and calculate net total SQL Query

I am finding it difficult to modify an existing SQL query to group records on two columns. Following is the query which retrieves records from multiple tables by joining:
SELECT
InM.invm_No AS DocNo,
InM.docs_DocCode,
D.doctyp_Desc AS DocType,
L.loc_Desc AS Site,
InM.sup_Code AS Supplier,
InD.invd_Qty,
InD.invd_Rate
FROM
[SI_InventoryMaster] InM
INNER JOIN
[SI_DocType] AS D ON InM.doctyp_Code = D.doctyp_Code
INNER JOIN
SI_Supplier S ON InM.sup_Code = S.sup_Code
INNER JOIN
[SI_InventoryDetail] AS InD ON InD.invm_No = InM.invm_No
AND InM.invm_verified = 1
AND InM.docs_DocCode = 'GRN'
AND MONTH (InM.invm_Date) = 12
AND YEAR(InM.invm_date) = 2013
INNER JOIN
SI_Location L ON InD.loc_code = L.loc_Code
ORDER BY
InM.invm_No
Which results the following:
I need to group records "by DocNo by Site" and find total amount for each site. Total amount will be last column in this resultset and it is net of product of InD.invd_Qty and InD.invd_Rate for each site.
For DocNo: 00000030, there are 4 records of CWS Store Site, so its total amount would be calculated as: 7684.999+7684.999+3000+3000=21369.998
In this particular example, modified query should return following resultset:
Please help.
Thanks.
Try grouping on all the columns associated with those two columns. Something like:
SELECT InM.invm_No AS DocNo, InM.docs_DocCode, D.doctyp_Desc AS DocType,
L.loc_Desc AS Site, InM.sup_Code AS Supplier,
sum(InD.invd_Qty),
sum(InD.invd_Rate)
FROM [SI_InventoryMaster] InM INNER JOIN
[SI_DocType] AS D
ON InM.doctyp_Code = D.doctyp_Code INNER JOIN
SI_Supplier S
ON InM.sup_Code = S.sup_Code INNER JOIN
[SI_InventoryDetail] AS InD
ON InD.invm_No = InM.invm_No AND
InM.invm_verified = 1 AND
InM.docs_DocCode = 'GRN' AND
MONTH (InM.invm_Date) = 12 AND
YEAR(InM.invm_date) = 2013 INNER JOIN
SI_Location L
ON InD.loc_code = L.loc_Code
GROUP BY InM.invm_No AS DocNo, InM.docs_DocCode, D.doctyp_Desc AS DocType,
L.loc_Desc AS Site, InM.sup_Code AS Supplier;