This question already has answers here:
Convert Rows to columns using 'Pivot' in SQL Server
(9 answers)
Closed 7 years ago.
My query:
select (sum( c20 ))as total , año
FROM(
select distinct datepart(year,DATEADD(DAY,CONVERT(FLOAT(10),KDUD.C16),A1.C7))as año, (a1.c20) as c20
from
KDUE A1
LEFT JOIN KDMM ON KDMM.C1='U' AND A1.C3=KDMM.C2 AND A1.C4=KDMM.C3 AND A1.C5=KDMM.C4
LEFT JOIN KDMS ON A1.C1=KDMS.C1
LEFT JOIN KDUD ON A1.C2=KDUD.C2
LEFT JOIN KDUV ON A1.C18=KDUV.C2
where a1.c20 != 0) as aas
group by año
this gives this table as a result:
total año
--------------------------------------- -----------
409782.45 2013
2442993.24 2014
10810460.01 2015
but i wish i could get the years as headers and the totals as a single row... help :c
with x as
(select (sum( c20 ))as total , año
FROM(
select distinct datepart(year,DATEADD(DAY,CONVERT(FLOAT(10),KDUD.C16),A1.C7))as año, (a1.c20) as c20
from
KDUE A1
LEFT JOIN KDMM ON KDMM.C1='U' AND A1.C3=KDMM.C2 AND A1.C4=KDMM.C3 AND A1.C5=KDMM.C4
LEFT JOIN KDMS ON A1.C1=KDMS.C1
LEFT JOIN KDUD ON A1.C2=KDUD.C2
LEFT JOIN KDUV ON A1.C18=KDUV.C2
where a1.c20 != 0) as aas
group by año)
select case when ano = '2013' then total end as '2013',
case when ano = '2014' then total end as '2014',
case when ano = '2015' then total end as '2015'
from x
This is one way to do it but will be more manual as you have more than a handful of values in ano column.
Related
This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 5 months ago.
Below calculates the SalesMonth, CountryName, SegmentName, PromotionRate and TotalMonthlySales of each segment within each country for each month from 1/1/2016 onwards.
with monthly_sales_info as (
select
Results top 3:
SalesMonth
CountryName
SegementName
PromotionRate
TotalMonthlySales
2016-03-01
Canada
Midmarket
0.106557
424880.85
2016-05-01
Canada
Midmarket
0.089285
159978
2016-02-01
France
Government
0.149821
524671.78
I now need to only return the top performing country/segment for each month from 1/1/2016. Multiple countries can have multiple segments. One segment is in one country.
You need to order the TotalMonthlySales value using RANK() window function
;with monthly_sales_info as (
select
sales_info.SalesMonth,
c.CountryName,
s.SegmentName,
sales_info.PromotionRate,
sales_info.TotalMonthlySales
from Region r
inner join Country c on c.CountryID = r.CountryID
inner join Segment s on s.SegmentID = r.SegmentID
inner join SalesRegion sr on sr.RegionID = r.RegionID
left join (
select
so.SalesRegionID,
so.SalesMonth,
sum(case when sli.PromotionID = 0 then 0.0 else 1.0 end) /
count(*) as PromotionRate,
sum(SalePrice) as TotalMonthlySales
from SalesOrder so
inner join SalesOrderLineItem sli on sli.SalesOrderID =
so.SalesOrderID
group by
so.SalesRegionID,
so.SalesMonth
) sales_info on sales_info.SalesRegionID = sr.SalesRegionID
),
top_monthly_sales_info AS(
select *,RANK() OVER(PARTITION BY YEAR(SalesMonth), MONTH(SalesMonth) ORDER BY TotalMonthlySales DESC) RankValue
from monthly_sales_info
where SalesMonth >= '2016-01-01')
SELECT SalesMonth, CountryName, SegmentName, PromotionRate, TotalMonthlySales
FROM top_monthly_sales_info
WHERE RankValue = 1
I have a query I've used to extract data from a database:
SELECT a.YOA YOA, a.Claim_Status_Type,
SUM(Cumulative_Total_Incurred_Cost*Exchange_Rate_Multiplier)AS
Cumulative_Total_Incurred_Cost
FROM F_Claims_Monthly_Snapshot a
inner join Dim_period b on (b.Period_Key = a.Accounting_Period_Key)
inner join tgt.Dim_BusinessDate c on (b.Month_End_Date_Key =
c.Business_Date_Key)
inner join tgt.Dim_BusinessUnit h on (a.Business_Unit_Key = h.Business_Unit_Key)
inner join tgt.Dim_Currency ccy on ccy.Currency_Key= a.Currency_Key
inner join tgt.Dim_Currency input_curr on input_curr.Currency_Key = a.Currency_Key
inner join tgt.Fct_CurrencyRate cr on cr.FROM_Currency_Key = a.Currency_Key and cr.Exchange_Date_Key = a.Month_End_Date_Key and Exchange_Rate_Type = 'Actual Rates'
inner join tgt.Dim_Currency report_curr on report_curr.Currency_Key = cr.To_Currency_Key and report_curr.Currency_Code='GBP'
inner join tgt.Dim_PRAClass i on (a.PRA_Class_Key=i.PRA_Class_Key)
inner join tgt.Dim_MasterAgreement j on (a.Master_Agreement_Key = j.Master_Agreement_Key)
inner join tgt.Dim_BusinessDate k on (a.Month_End_Date_Key = k.Business_Date_Key)
WHERE a.YOA between 2014 and 2018
and left(convert(date,(cast(a.Month_End_Date_Key as char(10))),3),8) = left(convert(date,(cast(First_Cost_Movement_Date_Key as char(10))),3),8)
and h.Business_Unit_name = 'Delegated Commercial'
GROUP BY a.YOA,i.PRA_Class,a.Claim_Status_Type;
The Query produces the following table:
YOA Claim_Status Total_Cost
2016 CLOSED 2266634.000000
2014 CLOSED 9880638.990000
2015 OPEN 5904188.060000
2016 CLOSED 4088.570000
2016 OPEN 3589749.000000
2015 CLOSED 22701.000000
2017 OPEN 1001.000000
2017 OPEN 844649.000000
2016 OPEN 6594017.000000
2014 OPEN 50000.000000
2017 OPEN 1835594.810000
2017 CLOSED 112805.000000
2016 CLOSED 4292586.25000
I would now like to alter the table above to look like below:
YOA Open_Total Closed_Total
2017 (SUM of all OPEN Status'for 2017) (SUM of all CLOSED Status' for 2017)
2016 (SUM of all OPEN Status'for 2016) (SUM of all CLOSED Status' for 2016)
2015 (SUM of all OPEN Status'for 2015) (SUM of all CLOSED Status' for 2015)
2014 (SUM of all OPEN Status'for 2014) (SUM of all CLOSED Status' for 2014)
So in short I would like to create a new query which will produce a table that will displayed the:
SUM of all OPEN total_costs for 2016 as new column called 'OPEN total'
SUM of all CLOSED total_costs for 2015 as new column called 'CLOSED_total'
Try with a CASE WHEN inside your SUM(..):
SELECT
a.YOA YOA,
SUM(CASE a.Claim_Status_Type
WHEN N'OPEN'
THEN Cumulative_Total_Incurred_Cost*Exchange_Rate_Multiplier
ELSE 0.0 END) AS Open_Cumulative_Total_Incurred_Cost,
SUM(CASE a.Claim_Status_Type
WHEN N'CLOSED'
THEN Cumulative_Total_Incurred_Cost*Exchange_Rate_Multiplier
ELSE 0.0 END) AS Closed_Cumulative_Total_Incurred_Cost
FROM F_Claims_Monthly_Snapshot a
inner join Dim_period b on (b.Period_Key = a.Accounting_Period_Key)
inner join tgt.Dim_BusinessDate c
on (b.Month_End_Date_Key = c.Business_Date_Key)
inner join tgt.Dim_BusinessUnit h on (a.Business_Unit_Key = h.Business_Unit_Key)
inner join tgt.Dim_Currency ccy on ccy.Currency_Key= a.Currency_Key
inner join tgt.Dim_Currency input_curr on input_curr.Currency_Key = a.Currency_Key
inner join tgt.Fct_CurrencyRate cr on cr.FROM_Currency_Key = a.Currency_Key and cr.Exchange_Date_Key = a.Month_End_Date_Key and Exchange_Rate_Type = 'Actual Rates'
inner join tgt.Dim_Currency report_curr on report_curr.Currency_Key = cr.To_Currency_Key and report_curr.Currency_Code='GBP'
inner join tgt.Dim_PRAClass i on (a.PRA_Class_Key=i.PRA_Class_Key)
inner join tgt.Dim_MasterAgreement j on (a.Master_Agreement_Key = j.Master_Agreement_Key)
inner join tgt.Dim_BusinessDate k on (a.Month_End_Date_Key = k.Business_Date_Key)
WHERE a.YOA between 2014 and 2018
and left(convert(date,(cast(a.Month_End_Date_Key as char(10))),3),8) = left(convert(date,(cast(First_Cost_Movement_Date_Key as char(10))),3),8)
and h.Business_Unit_name = 'Delegated Commercial'
GROUP BY a.YOA;
select yoa, sum(case when claimstatus='open' then Total_Cost else null end) open_total,
sum(case when claimstatus='closed' then Total_Cost else null end) closed_total
from table_name
group by yoa
I need a SQL query to return a row for every month in years 2015 and 2016 for every company that pays dues. The resulting dataset will show which months the company didn't pay dues by a null value. The problem is that if they didn't pay dues they won't have an entry in the database so no row will appear for than month. Here is the query:
SELECT
case when n.co_id <>'' then n.co_id else n.ID end ID
,su.CONTINUOUS_SINCE
,n.COMPANY
,a.EFFECTIVE_DATE
, a.AMOUNT
FROM dbo.Name n
LEFT OUTER JOIN dbo.Activity a ON n.ID = a.ID
inner JOIN dbo.Loc_Info l ON n.ID = l.ID
inner JOIN dbo.Segment_Categories s ON l.CURRENT_SEGMENT = s.CODE
inner JOIN dbo.Subscriptions su on su.id=n.id
WHERE a.PRODUCT_CODE='rental' and n.MEMBER_TYPE in ('rb','rl') and a.EFFECTIVE_DATE Between '2015-07-01' And GetDate() AND a.ACTIVITY_TYPE='dues'
order by case when n.co_id <>'' then n.co_id else n.ID end, EFFECTIVE_DATE asc
If the company has paid every month it works out fine but the point is to find the companies that haven't paid so suppose Company XYZ paid every month in 2015 except June I need a row for June for Company XYZ that has a NULL value or a zero or some other indicator that they missed a payment. As it stands now the row is simply omitted because the data isn't there and it is hard to find a missing row out of thousands or rows.
I realize it is probably a different type of join or something but I am just not getting it to work out.
You can create a dummy table for the months, left join the dbo.Activity to it, that way you'll get all the months, and then join that to dbo.Name
1) Generate all the months from 1 to 12 with a recursive cte.
2) Get all months years and companies combinations with a cross join.
3) left join on this result-set to show missing months.
with months as (select 1 mth
union all
select mth+1 from months where mth<12)
,yearmonthscompanies as (select *
from months m
cross join (select 2015 yr union all select 2016 yr) y
cross join (select distinct id,co_id,company from name) c
)
SELECT
case when ymc.co_id <>'' then ymc.co_id else ymc.ID end ID
,su.CONTINUOUS_SINCE
,ymc.COMPANY
,coalesce(a.effective_date,datefromparts(ymc.yr,ymc.mth,1)) as effective_date
,coalesce(a.AMOUNT,0) amount
FROM yearmonthscompanies ymc
LEFT JOIN dbo.Name n ON n.co_id=ymc.co_id and n.id=ymc.id and n.company=ymc.company
LEFT JOIN dbo.Activity a ON n.ID = a.ID and a.PRODUCT_CODE='rental'
and n.MEMBER_TYPE in ('rb','rl') and a.EFFECTIVE_DATE Between '2015-07-01' and GetDate()
and a.ACTIVITY_TYPE='dues'
and year(a.effective_date) = ymc.yr and month(a.effective_date) = ymc.mth
inner JOIN dbo.Loc_Info l ON n.ID = l.ID
inner JOIN dbo.Segment_Categories s ON l.CURRENT_SEGMENT = s.CODE
inner JOIN dbo.Subscriptions su on su.id=n.id
order by case when ymc.co_id <>'' then ymc.co_id else ymc.ID end
,effective_date
I am working with the below query
SELECT * FROM
(SELECT DISTINCT
a.Number
,a.Description
,ISNULL(temp.Quantity,0) Quantity
,LastReceived
,LastIssued
FROM Article a
LEFT JOIN (
select ss.ArticleId
, ss.Quantity
, max(lastreceiveddate) as LastReceived
, max(lastissueddate) as LastIssued
from StockSummary ss
where ss.UnitId = 8
group by ss.ArticleId, ss.StockQuantity
having (MAX(ss.LastReceivedDate) < '2014-09-01' or MAX(ss.LastReceivedDate) is NULL)
AND (MAX(ss.LastIssuedDate) < '2014-09-01' or MAX(ss.LastIssuedDate) is NULL)
) temp on a.Id = temp.ArticleId
WHERE a.UnitId = 8
) main
ORDER BY main.Number
What i want to achieve is to select the articles only with the MAX(ss.LastReceivedDate) and MAX(ss.LastIssuedDate) condition in the Left join query and then do the Quantity Select in the main query.
Note: the quantity column can be 0 or NULL.
Kindly help
I m using the following query, to get the result as shown below. Actually the query is just joining 2 tables.
SELECT MT.mkt_Area_ID,MA.mkt_Reg_ID,MT.mktcate_id,MT.target_Amt,MT.year
FROM [CRM].[tblMktArea_Target] MT JOIN CRM.tblMarketingArea MA
ON MA.mkt_Area_ID= MT.mkt_Area_ID WHERE month IN (05,04) AND year=2013 AND MA.mkt_Area_ID=1
AND MA.mkt_Reg_ID =1
How can I group the results by mktcate_id to get the sum of target_amt for each category?
I tried:
SELECT MT.mkt_Area_ID,MA.mkt_Reg_ID,MT.mktcate_id,Sum(MT.target_Amt),MT.year
FROM [CRM].[tblMktArea_Target] MT JOIN CRM.tblMarketingArea MA
ON MA.mkt_Area_ID= MT.mkt_Area_ID WHERE month IN (05,04) AND year=2013 AND MA.mkt_Area_ID=1
AND MA.mkt_Reg_ID =1 group by MT.mktcate_id
and getting errror
You are getting an exception because it is necessary to add non-aggregated columns in the GROUP BY clause. Example,
SELECT MT.mkt_area_id,
MA.mkt_reg_id,
MT.mktcate_id,
SUM(MT.target_amt),
MT.year
FROM [CRM].[TBLMKTAREA_TARGET] MT
JOIN CRM.TBLMARKETINGAREA MA
ON MA.mkt_area_id = MT.mkt_area_id
WHERE month IN ( 05, 04 )
AND year = 2013
AND MA.mkt_area_id = 1
AND MA.mkt_reg_id = 1
GROUP BY MT.mktcate_id,
MT.mkt_area_id,
MA.mkt_reg_id,
MT.year
You should always GROUP BY on all the columns that are not within aggregate functions (such as SUM, MAX, AVG).
Put MT.mkt_Area_ID, MA.mkt_Reg_ID, MT.year fields into the GROUP BY clause:
SELECT MT.mkt_Area_ID,
MA.mkt_Reg_ID,
MT.mktcate_id,
Sum(MT.target_Amt),
MT.year
FROM [CRM].[tblMktArea_Target] MT JOIN CRM.tblMarketingArea MA ON
MA.mkt_Area_ID = MT.mkt_Area_ID
WHERE month IN (05,04) AND
year = 2013 AND
MA.mkt_Area_ID = 1 AND
MA.mkt_Reg_ID = 1
GROUP BY MT.mktcate_id,
MT.mkt_Area_ID,
MA.mkt_Reg_ID,
MT.year
Or remove MT.mkt_Area_ID, MA.mkt_Reg_ID, MT.year fields from the SELECT clause:
SELECT MT.mktcate_id,
Sum(MT.target_Amt)
FROM [CRM].[tblMktArea_Target] MT JOIN CRM.tblMarketingArea MA ON
MA.mkt_Area_ID = MT.mkt_Area_ID
WHERE month IN (05,04) AND
year = 2013 AND
MA.mkt_Area_ID = 1 AND
MA.mkt_Reg_ID = 1
GROUP BY MT.mktcate_id