SQL Server Query to Pivot using CASE Statement - sql

I have the following data:
763b44e57b39-16e5bb772ac November Monthly Mailer MM_10 191201-1 2019-12-01 00:00:00.000 2020-01-01 00:00:00.000
763b44e57b39-16e5bb772ac November Monthly Mailer MM_10 191208-2 2019-12-01 00:00:00.000 2020-01-01 00:00:00.000
763b44e57b39-16e5bb772ac November Monthly Mailer MM_10 191215-3 2019-12-01 00:00:00.000 2020-01-01 00:00:00.000
763b44e57b39-16e5bb772ac November Monthly Mailer MM_10 191222-4 2019-12-01 00:00:00.000 2020-01-01 00:00:00.000
763b57fe9950-16dac7db279 October Monthly Mailer MM_10 191001-1 2019-10-01 00:00:00.000 2019-11-01 00:00:00.000
763b57fe9950-16dac7db279 October Monthly Mailer MM_10 191008-2 2019-10-01 00:00:00.000 2019-11-01 00:00:00.000
763b57fe9950-16dac7db279 October Monthly Mailer MM_10 191015-3 2019-10-01 00:00:00.000 2019-11-01 00:00:00.000
763b57fe9950-16dac7db279 October Monthly Mailer MM_10 191022-4 2019-10-01 00:00:00.000 2019-11-01 00:00:00.000
763b57ff55b7-16dad4ef4b8 November Monthly Mailer MM_10 191101-1 2019-11-01 00:00:00.000 2019-12-01 00:00:00.000
763b57ff55b7-16dad4ef4b8 November Monthly Mailer MM_10 191108-2 2019-11-01 00:00:00.000 2019-12-01 00:00:00.000
763b57ff55b7-16dad4ef4b8 November Monthly Mailer MM_10 191115-3 2019-11-01 00:00:00.000 2019-12-01 00:00:00.000
763b57ff55b7-16dad4ef4b8 November Monthly Mailer MM_10 191122-4 2019-11-01 00:00:00.000 2019-12-01 00:00:00.000
763b5803a370-16dcb7cfd7e 11th Anniversary Celebration SBR $15 Sky Ute Loot 2019-11-01 00:00:00.000 2019-11-02 00:00:00.000
I need to create a Pivot using CASE statement so that the results looks like:
763b44e57b39-16e5bb772ac MM_10 191201-1 MM_10 191208-2 MM_10 191215-3 MM_10 191222-4
763b57fe9950-16dac7db279 MM_10 191001-1 MM_10 191008-2 MM_10 191015-3 MM_10 191022-4
What's the best way to do this using a CASE statement?

If you use ROW_NUMBER to generate a sequential number, then that can be used in the conditional aggregations.
SELECT Campaign_id,
MAX(CASE WHEN Rn = 1 THEN RIGHT(Campaign_name, 5) END) AS CampaignCode1,
MAX(CASE WHEN Rn = 1 THEN Offer_name END) AS OfferName1,
MAX(CASE WHEN Rn = 2 THEN RIGHT(Campaign_name, 5) END) AS CampaignCode2,
MAX(CASE WHEN Rn = 2 THEN Offer_name END) AS OfferName2,
MAX(CASE WHEN Rn = 3 THEN RIGHT(Campaign_name, 5) END) AS CampaignCode3,
MAX(CASE WHEN Rn = 3 THEN Offer_name END) AS OfferName3,
MAX(CASE WHEN Rn = 4 THEN RIGHT(Campaign_name, 5) END) AS CampaignCode4,
MAX(CASE WHEN Rn = 4 THEN Offer_name END) AS OfferName4
FROM
(
SELECT Campaign_id, Campaign_name, Offer_name,
ROW_NUMBER() OVER (PARTITION BY Campaign_id ORDER BY REVERSE(Offer_name)) AS Rn
FROM YourTable
) AS Src
GROUP BY Campaign_id
ORDER BY Campaign_id;

Related

SQL Server query Group By Trimester

I'm finding a way to group SQL query by trimester. I have found a way to do it using MySQL on this link.
This is what I'm expecting:
Range Start Range End Count
----------- ---------- -----
2013-09-01 2013-11-26 87
2013-06-01 2013-08-31 92
2013-03-01 2013-05-31 92
2012-12-01 2013-02-28 90
2012-09-01 2012-11-30 91
This is what I have tried:
SELECT MIN(start_date) AS Range_Start, MAX(start_date) AS Range_End, COUNT(ID) AS Total
FROM [dbo].[table]
GROUP BY FLOOR(DATEDIFF(MONTH, DATEADD(DAY, -DAY(start_date)+1, start_date), DATEADD(DAY, -DAY(start_date)+1,getdate())) /3)
ORDER BY 1 ASC
This is what I get:
Range Start Range End Count
----------- ---------- -----
1900-01-01 00:00:00.000 1900-01-01 00:00:00.000 8
1952-01-01 00:00:00.000 1952-01-01 00:00:00.000 2
1954-01-01 00:00:00.000 1954-01-01 00:00:00.000 11
1955-01-01 00:00:00.000 1955-01-01 00:00:00.000 3
1956-01-01 00:00:00.000 1956-01-01 00:00:00.000 2
1957-01-01 00:00:00.000 1957-01-01 00:00:00.000 8
1958-01-01 00:00:00.000 1958-01-01 00:00:00.000 2
1959-01-01 00:00:00.000 1959-01-01 00:00:00.000 5
1960-01-01 00:00:00.000 1960-01-01 00:00:00.000 17
1960-03-17 00:00:00.000 1960-03-17 00:00:00.000 1

SQL Server : compare rows, exclude from results when some values are the same

I have the following SQL Server query problem.
If there is a row where Issue_DATE = as Maturity_Date in another row, and if both rows have the same ID and Amount USD, then none of these rows should be displayed.
Here is a simplified version of my table:
ID ISSUE_DATE MATURITY_DATE AMOUNT_USD
1 2010-01-01 00:00:00.000 2015-12-01 00:00:00.000 5000
1 2010-01-01 00:00:00.000 2001-09-19 00:00:00.000 700
2 2014-04-09 00:00:00.000 2019-04-09 00:00:00.000 400
1 2015-12-01 00:00:00.000 2016-12-31 00:00:00.000 5000
5 2015-02-24 00:00:00.000 2015-02-24 00:00:00.000 8000
4 2012-11-29 00:00:00.000 2015-11-29 00:00:00.000 10000
3 2015-01-21 00:00:00.000 2018-01-21 00:00:00.000 17500
2 2015-02-02 00:00:00.000 2015-12-05 00:00:00.000 12000
1 2015-01-12 00:00:00.000 2018-01-12 00:00:00.000 18000
2 2015-12-05 00:00:00.000 2016-01-10 00:00:00.000 12000
Result should be:
ID ISSUE_DATE MATURITY_DATE AMOUNT_USD
1 2010-01-01 00:00:00.000 2001-09-19 00:00:00.000 700
2 2014-04-09 00:00:00.000 2019-04-09 00:00:00.000 400
5 2015-02-24 00:00:00.000 2015-02-24 00:00:00.000 8000
4 2012-11-29 00:00:00.000 2015-11-29 00:00:00.000 10000
3 2015-01-21 00:00:00.000 2018-01-21 00:00:00.000 17500
1 2015-01-12 00:00:00.000 2018-01-12 00:00:00.000 18000
I tried with self join, but I do not get right result.
Thanks in advance!
Can you try something like this? 'not exists' is the way of doing it.
select * from table t1 where not exists (select 'x' from table t2 where t1.issue_date = t2.maturity_date and t1.amount_usd=t2.amount_usd and t1.id = t2.id)
I'd think about making subquery of all the dupes and then eliminating them from the first table like so:
select t1.ID
, t1.ISSUE_DATE
, t1.MATURITY_DATE
, t1.AMOUNT_USD
FROM
t1
LEFT JOIN
(select a.ID
, a.ISSUE_DATE
, a.MATURITY_DATE
, a.AMOUNT_USD
FROM
t1 a
INNER JOIN
ti b
) dupes
on
t1.ID = dupes.ID
WHERE dupes.ID IS NULL;

SQL Server query join several tables

I have a query that I don't think should be that hard to make, however, I've spent a lot of time on it now and still can't get it the way I want, so I hope someone here can help me.
Basically, I need to create a report that will give a value for each month, for each area. However, not all areas deliver data each month; in that case the view should return NULL for that month and area. So, the view need to look something like this:
Month Area Value
2012-08-01 Area1 2
2012-08-01 Area2 3
2012-09-01 Area1 3
2012-09-01 Area2 NULL
My data table looks something like this
Date Area Value
2012-08-01 Area1 2
2012-08-01 Area2 3
2012-09-01 Area1 3 -- Notice that Area2 is not present for September here
I have a table with all the available areas
Furthermore, I have created a table-valued function that returns all dates from a given date until now.
For example this statement
SELECT * FROM Periods_Months('2012-01-01')
would return 8 records like:
DateValue Year Month YearMonth
2012-01-01 00:00:00.000 2012 1 20121
2012-02-01 00:00:00.000 2012 2 20122
2012-03-01 00:00:00.000 2012 3 20123
2012-04-01 00:00:00.000 2012 4 20124
2012-05-01 00:00:00.000 2012 5 20125
2012-06-01 00:00:00.000 2012 6 20126
2012-07-01 00:00:00.000 2012 7 20127
2012-08-01 00:00:00.000 2012 8 20128
Based on the suggestions, my query now looks like this:
WITH months AS (
SELECT DateValue, YearMonth FROM Periods_Months('2011-01-01')
)
select m.DateValue
,CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,m.DateValue)+1,0)) AS Date) AS DateReported -- Get last day in month
,ResponseTime AS Value
,g.ExternalId
from GISDB.dbo.GisObjects g
CROSS JOIN months m
LEFT OUTER JOIN
( -- SELECT data from data table, grouped by area and month
SELECT dbo.YearMonth(CloseDate) AS YearMonth
,MAX(CloseDate) AS LastDate
,GisObjectId
,SUM(DATEDIFF(HH,RegDate,CloseDate)) AS ResponseTime -- calculate response time between start and end data (the value we need)
FROM DataTable
WHERE CloseDate IS NOT NULL
AND GisObjectId IS NOT NULL
GROUP BY GisObjectId, dbo.YearMonth(CloseDate) -- group by area and month
) c
ON g.ObjectId = c.GisObjectId AND c.YearMonth = m.YearMonth
WHERE g.CompanyId = 3 AND g.ObjectTypeId = 1 -- reduce the GIS objects that we compare to
ORDER BY m.DateValue, g.ObjectId
But the result is this (Value is always NULL):
DateValue DateReported Value ExternalId
2011-01-01 00:00:00.000 31-01-2011 NULL 9994
2011-01-01 00:00:00.000 31-01-2011 NULL 9993
2011-01-01 00:00:00.000 31-01-2011 NULL 9992
2011-01-01 00:00:00.000 31-01-2011 NULL 9991
2011-01-01 00:00:00.000 31-01-2011 NULL 2339
2011-01-01 00:00:00.000 31-01-2011 NULL 2338
2011-01-01 00:00:00.000 31-01-2011 NULL 2337
2011-01-01 00:00:00.000 31-01-2011 NULL 2336
2011-01-01 00:00:00.000 31-01-2011 NULL 2335
2011-01-01 00:00:00.000 31-01-2011 NULL 2334
2011-01-01 00:00:00.000 31-01-2011 NULL 2327
2011-01-01 00:00:00.000 31-01-2011 NULL 2326
2011-01-01 00:00:00.000 31-01-2011 NULL 2325
2011-01-01 00:00:00.000 31-01-2011 NULL 2324
2011-01-01 00:00:00.000 31-01-2011 NULL 2323
2011-01-01 00:00:00.000 31-01-2011 NULL 2322
etc.
I suppose you have a table with all your areas, which I call area_table.
WITH month_table AS (
SELECT dateValue FROM Periods_Months('2012-01-01')
)
select * from area_table
CROSS JOIN month_table
LEFT OUTER JOIN myValueTable
ON area_table.name = myValueTable.area
AND myValueTable.date = left(convert(varchar(30),month_table.dateValue,120),10)
ORDER BY myValueTable.Month, myValueTable.area
Suppose Areas is your table for all available areas, t - is your data table:
SELECT pm.dateValue,Ar.Area, t.value
FROM Periods_Months('2012-01-01') pm, Areas ar
left join t on (pm.dateValue=t.Date) and (ar.Area=t.Area)
order by pm.DateValue,ar.Area

joining monthly values with daily values in sql

I have daily values in one table and monthly values in another table. I need to use the values of the monthly table and calculate them on a daily basis.
basically, monthly factor * daily factor -- for each day
thanks!
I have a table like this:
2010-12-31 00:00:00.000 28.3
2010-09-30 00:00:00.000 64.1
2010-06-30 00:00:00.000 66.15
2010-03-31 00:00:00.000 12.54
and a table like this :
2010-12-31 00:00:00.000 98.1
2010-12-30 00:00:00.000 97.61
2010-12-29 00:00:00.000 99.03
2010-12-28 00:00:00.000 97.7
2010-12-27 00:00:00.000 96.87
2010-12-23 00:00:00.000 97.44
2010-12-22 00:00:00.000 97.76
2010-12-21 00:00:00.000 96.63
2010-12-20 00:00:00.000 95.47
2010-12-17 00:00:00.000 95.2
2010-12-16 00:00:00.000 94.84
2010-12-15 00:00:00.000 94.8
2010-12-14 00:00:00.000 94.1
2010-12-13 00:00:00.000 93.88
2010-12-10 00:00:00.000 93.04
2010-12-09 00:00:00.000 91.07
2010-12-08 00:00:00.000 90.89
2010-12-07 00:00:00.000 92.72
2010-12-06 00:00:00.000 93.05
2010-12-03 00:00:00.000 91.74
2010-12-02 00:00:00.000 90.74
2010-12-01 00:00:00.000 90.25
I need to take the value for the quarter and multiply it buy all the days in the quarter by the daily value
You could try:
SELECT dt.day, dt.factor*mt.factor AS daily_factor
FROM daily_table dt INNER JOIN month_table mt
ON YEAR(dt.day) = YEAR(mt.day)
AND FLOOR((MONTH(dt.day)-1)/3) = FLOOR((MONTH(mt.day)-1)/3)
ORDER BY dt.day
or (as suggested by #Andriy)
SELECT dt.day, dt.factor*mt.factor AS daily_factor
FROM daily_table dt INNER JOIN month_table mt
ON YEAR(dt.day) = YEAR(mt.day)
AND DATEPART(QUARTER, dt.day) = DATEPART(QUARTER, mt.day)
ORDER BY dt.day

How to set in one date range using sql?

my dates
Dates
2011-03-01 00:00:00.000
2011-03-03 00:00:00.000
2011-03-07 00:00:00.000
2011-03-08 00:00:00.000
2011-03-13 00:00:00.000
2011-03-14 00:00:00.000
2011-03-15 00:00:00.000
How to convert this dates in to one date range like below
i need output like this'
Date_from Date_to
2011-03-01 00:00:00.000 2011-03-01 00:00:00.000
2011-03-03 00:00:00.000 2011-03-03 00:00:00.000
2011-03-07 00:00:00.000 2011-03-08 00:00:00.000
2011-03-13 00:00:00.000 2011-03-15 00:00:00.000
SQL Server 2005+
;WITH cte
AS (SELECT *,
DATEDIFF(DAY, 0, Dt) -
DENSE_RANK() OVER (ORDER BY DATEDIFF(DAY,0,Dt) ) AS Grp
FROM Dates)
SELECT MIN(Dt) AS Date_from,
MAX(Dt) AS Date_to
FROM cte
GROUP BY Grp