Update table but use a value from column - select case - sql

Not sure if this is possible, but I have a field in a table which needs to be updated by a value from another table, but references a specific column e.g. if it's 1 then get the value out of the [Jan] column etc.
Update table1
Set Total =
CASE #count
WHEN 1 THEN [Jan]
WHEN 2 THEN [Feb]
WHEN 3 THEN [Mar]
WHEN 4 THEN [Apr]
WHEN 5 THEN [May]
WHEN 6 THEN [Jun]
WHEN 7 THEN [Jul]
WHEN 8 THEN [Aug]
WHEN 9 THEN [Sep]
WHEN 10 THEN [Oct]
WHEN 11 THEN [Nov]
WHEN 12 THEN [Dec]
END
from table2
Thanks in advance

Update t
Set t.Total =
CASE #count
WHEN 1 THEN t2.[Jan]
WHEN 2 THEN t2.[Feb]
WHEN 3 THEN t2.[Mar]
WHEN 4 THEN t2.[Apr]
WHEN 5 THEN t2.[May]
WHEN 6 THEN t2.[Jun]
WHEN 7 THEN t2.[Jul]
WHEN 8 THEN t2.[Aug]
WHEN 9 THEN t2.[Sep]
WHEN 10 THEN t2.[Oct]
WHEN 11 THEN t2.[Nov]
WHEN 12 THEN t2.[Dec]
END
from table1 t inner join table2 t2
on t.ID = t2.ID --your condition

You could put the CASE in a sub-query:
UPDATE table1
SET Total=(SELECT TOP 1 CASE #count
WHEN 1 THEN [Jan]
WHEN 2 THEN [Feb]
WHEN 3 THEN [Mar]
WHEN 4 THEN [Apr]
WHEN 5 THEN [May]
WHEN 6 THEN [Jun]
WHEN 7 THEN [Jul]
WHEN 8 THEN [Aug]
WHEN 9 THEN [Sep]
WHEN 10 THEN [Oct]
WHEN 11 THEN [Nov]
WHEN 12 THEN [Dec]
END
FROM table2)

You can use UNPIVOT for this.
UPDATE Table2
SET [Total] =
(
SELECT B.[Total]
FROM
(
SELECT [Jan], [Feb], [Mar], [Apr], [May], [Jun]
, [Jul], [Aug], [Sep], [Oct], [Nov], [Dec]
FROM Table2
) AS A ([1], [2], [3], [4], [5], [6]
, [7], [8], [9], [10], [11], [12])
UNPIVOT ([Total] FOR [Month] IN
([1], [2], [3], [4], [5], [6]
, [7], [8], [9], [10], [11], [12])) B
WHERE B.[Month] = #count
)

Related

Is it possible to build this table using SQL?

I have 2 tables, a Sales table and a Payment table structured like the below.
The 2 are joined using the ContractID column. What I want to see is a matrix that shows me at the top, the sum of (sold amount) per monthyear. Then on the left, I want to see the payment dates by month year, and any payments that have been made. My ideal output would look like the below.
The yellow line being the total sold by month-year, and the green lines being all the payments that have been made from the payments table. I don't really know where to start with this one, does anyone have any advice on how to achieve this? I am going to unpivot the sold table first to get my dates across the top, just pondering the next step to pull this table together?
If I didn't understand wrong, it should be like this.
WITH PaymentMatrix
AS
(
SELECT
PaymentMonth,
SoldAmount,
[1] AS Jan,
[2] AS Feb,
[3] AS Mrz,
[4] AS Apr,
[5] AS Mai,
[6] AS Jun,
[7] AS Jul,
[8] AS Aug,
[9] AS Sep,
[10] AS Okt,
[11] AS Nov,
[12] AS Dez
FROM
(
Select
MONTH(S.SoldDate) as SoldMonth,
MONTH(P.PaymentDate) as PaymentMonth,
SUM(S.SoldAmount) as SoldAmount,
SUM(P.PaymentAmount) as PaymentAmount
from Sales S
INNER JOIN Payment P ON S.ContractID = P.ContractID
GROUP BY
MONTH(S.SoldDate),
MONTH(P.PaymentDate)
) source
PIVOT
(
SUM(PaymentAmount)
FOR SoldMonth
IN ( [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12] )
) AS pvtMonth
)
SELECT
PaymentMonth,
SUM(SoldAmount) AS Sold,
sum(Jan)as Jan , sum(Feb) as Feb, sum(Mrz) as Mrz, sum(Apr) as Apr, sum(Mai) as Mai,
sum(Jun)as Jun , sum(Jul) as Jul, sum(Aug) as Aug, sum(Sep) as Sep, sum(Okt) as Okt,
sum(Nov) as Nov, sum(Dez) as Dez
FROM PaymentMatrix
GROUP BY PaymentMonth
Fidler Sample
Sample Image
I suggest using conditional aggregation and a union.
Since the PIVOT syntax is more limited.
SELECT [Sold], [Jan-22], [Feb-22], [Mar-22]
FROM
(
SELECT 0 as Seq, 'Paid' AS [Sold]
, SUM(CASE WHEN FORMAT([Sold Date],'MMM-yy') = 'Jan-22'
THEN [Sold Amount] ELSE 0 END) AS [Jan-22]
, SUM(CASE WHEN FORMAT([Sold Date],'MMM-yy') = 'Feb-22'
THEN [Sold Amount] ELSE 0 END) AS [Feb-22]
, SUM(CASE WHEN FORMAT([Sold Date],'MMM-yy') = 'Mar-22'
THEN [Sold Amount] ELSE 0 END) AS [Mar-22]
FROM Sales
UNION ALL
SELECT m.Seq, m.PaymentMonth
, SUM(CASE WHEN SoldMonth = 'Jan-22' THEN PaymentAmount ELSE 0 END) AS [Jan-22]
, SUM(CASE WHEN SoldMonth = 'Feb-22' THEN PaymentAmount ELSE 0 END) AS [Feb-22]
, SUM(CASE WHEN SoldMonth = 'Mar-22' THEN PaymentAmount ELSE 0 END) AS [Mar-22]
FROM (VALUES
(1,'Jan-22'),
(2,'Feb-22'),
(3,'Mar-22')
) m(Seq, PaymentMonth)
LEFT JOIN (
SELECT ContractID
, FORMAT(EOMONTH([Payment Date]), 'MMM-yy') AS PaymentMonth
, SUM([Payment Amount]) AS PaymentAmount
FROM Payment
GROUP BY ContractID, EOMONTH([Payment Date])
) p ON p.PaymentMonth = m.PaymentMonth
LEFT JOIN (
SELECT ContractID
, FORMAT(MAX([Sold Date]), 'MMM-yy') AS SoldMonth
, SUM([Sold Amount]) AS SoldAmount
FROM Sales
GROUP BY ContractID
) s ON s.ContractID = p.ContractID
GROUP BY m.Seq, m.PaymentMonth
) q
ORDER BY Seq;
Sold
Jan-22
Feb-22
Mar-22
Paid
2500
100
0
Jan-22
300
0
0
Feb-22
400
50
0
Mar-22
0
0
0
Test on db<>fiddle here

rename columns in SQL Query transpose

I have a SQL query than transpose rows by columns but i dont know how to rename the columns.
select *
from
(select CustomerID, FiscalPeriod, SaleAmtLocalCurr
from PerfTrk.dbo.IRIS_SaleFact
where CountryCode = '00001'
and DivisionCode = 'INS'
and SaleAmtLocalCurr > 0
and datefromparts(FiscalYear, FiscalPeriod, 1) between datefromparts(2019,9, 1) and datefromparts(2020,8, 31)) d
pivot
(sum(SaleAmtLocalCurr) for FiscalPeriod in ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
) piv;
The result is
CustomerID 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
I want to rename the columns with the names of months
Thanks
CASE is always an option
select
*
from
(select
CustomerID,
(CASE
WHEN FiscalPeriod = 1 THEN 'JAN'
WHEN FiscalPeriod = 2 THEN 'FEB'
WHEN FiscalPeriod = 3 THEN 'MAR'
WHEN FiscalPeriod = 4 THEN 'APR'
WHEN FiscalPeriod = 5 THEN 'MAY'
WHEN FiscalPeriod = 6 THEN 'JUN'
WHEN FiscalPeriod = 7 THEN 'JUL'
WHEN FiscalPeriod = 8 THEN 'AUG'
WHEN FiscalPeriod = 9 THEN 'SEP'
WHEN FiscalPeriod = 10 THEN 'OCT'
WHEN FiscalPeriod = 11 THEN 'NOV'
WHEN FiscalPeriod = 12 THEN 'DEC'
END) AS 'Month',
SaleAmtLocalCurr
from
PerfTrk.dbo.IRIS_SaleFact
where
CountryCode = '00001'
and DivisionCode = 'INS'
and SaleAmtLocalCurr > 0
and datefromparts(FiscalYear, FiscalPeriod, 1)
between datefromparts(2019,9, 1) and datefromparts(2020,8, 31)) d
pivot
(sum(SaleAmtLocalCurr) for FiscalPeriod in ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
) piv;

Pivot SQL - Where header includes a DISTINCT and DatePart (data conversion) field

I'm trying to adjust the following output to a pivotted table, but I'm struggling and the Distinct and DatePart (data conversions) are impacting it. (I have to use DatePart, datetrunc() isn't available to me).
ORIGINAL
SELECT DISTINCT (DatePart(Week, S.Date_)) AS Week, T.NAME,SUM([Call Count]) AS TotalCallCount
FROM Sched S LEFT JOIN
SchedTy T
ON S.schedTy_Id = T.id INNER JOIN
Events a
ON a.[Event Id] = s.id
WHERE [Call Count] > 0 AND S.Status_id > 0 AND a.DATE BETWEEN '1/1/2019' AND '1/1/2020'
GROUP BY T.Name, DatePart(Week, S.Date_)
ORIGINAL OUTPUT
Week EventType TotalCallCount
1 Public Holiday 6
3 B 1
3 P 3
3 R 9
4 Rec 12
4 R 3
5 P 3
5 R 15
6 Rec 18
7 P 3
7 Rec 6
7 R 12
8 B 1
8 P 6
8 R 18
9 B 1
9 CDM 3
9 P 6
9 R 15
10 OP 3
DESIRED OUTPUT (EITHER)
Wk1 Wk2 Wk3 Wk4
Public Holiday
R
P
Rec
OR
Public Holiday R P Rec
Wk1
Wk2
Wk3
Wk4
I have tried:
Attempt 1
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR (MAX) SELECT #cols = STUFF((SELECT ‘,’ + DISTINCT (DatePart(Week, S.Date_))FROM Sched S ORDER By S.Date_ FOR XML PATH(‘’),TYPE).value(‘.’‘NVARCGAR(MAX)’),1,1,’’) Set #query = ‘SELECT T.Name AS EventType,’ + #cols FROM ( SELECT T.Name, S.Date, [Call Count] FROM Sched S LEFT JOIN SchedTy T ON S.schedTy_Id = T.id INNER JOIN Events a ON a.[Event Id] = s.id WHERE [Call Count] > 0 AND S.Status_id > 0 AND a.DATE BETWEEN '1/1/2019'AND '1/1/2020') PIVOT(sum([Call Count]) FOR s.Date_ in ('' + #cols + '')) p Execute(#query)
Attempt 2
SELECT T.Name, [1] AS Wk1, [2] AS Wk2, [3] AS Wk3, [4] AS Wk4, [5] AS Wk5, [6] AS Wk6, [7] AS Wk7, [8] AS Wk8, [9] AS Wk9, [10] AS Wk10, [11] AS Wk11, [12] AS Wk12, [13] AS Wk13, [14] AS Wk14, [15] AS Wk15, [16] AS Wk16, [17] AS Wk17, [18] AS Wk18, [19] AS Wk19, [20] AS Wk20, [21] AS Wk21, [22] AS Wk22, [23] AS Wk23, [24] AS Wk24, [25] AS Wk25, [26] AS Wk26, [27] AS Wk27, [28] AS Wk28, [29] AS Wk29, [30] AS Wk30, [31] AS Wk31, [32] AS Wk32, [33] AS Wk33, [34] AS Wk34, [35] AS Wk35, [36] AS Wk36, [37] AS Wk37, [38] AS Wk38, [39] AS Wk39, [40] AS Wk40, [41] AS Wk41, [42] AS Wk42, [43] AS Wk43, [44] AS Wk44, [45] AS Wk45, [46] AS Wk46, [47] AS Wk47, [48] AS Wk48, [49] AS Wk49, [10] AS Wk50, [51] AS Wk51, [52] AS Wk52 FROM (SELECT DISTINCT (DatePart(Week, S.Date_)) AS Week, T.NAME, ([Call Count]) FROM Sched S LEFT JOIN SchedTy T ON S.schedTy_Id = T.id INNER JOIN Events a ON a.[Event Id] = s.id WHERE [Call Count] > 0 AND S.Status_id > 0 AND a.DATE BETWEEN '1/1/2019' AND '1/1/2020') AS TotalCallCount PIVOT (SUM([Call Count]) FOR(DatePart(Week, S.Date_)) IN [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31], [32], [33], [34], [35], [36], [37], [38], [39], [40], [41], [42], [43], [44], [45], [46], [47], [48], [49], [50], [51], [52])AS pvt
I think you can just use conditional aggregation:
SELECT DatePart(Week, S.Date_) AS Week, T.NAME,
SUM(CASE WHEN T.NAME = 'Public Holiday' THEN [Call Count] END) AS total_public_holiday,
SUM(CASE WHEN T.NAME = 'B' THEN [Call Count] END) AS total_b,
SUM(CASE WHEN T.NAME = 'P' THEN [Call Count] END) AS total_p,
SUM(CASE WHEN T.NAME = 'R' THEN [Call Count] END) AS total_r,
SUM(CASE WHEN T.NAME = 'Rec' THEN [Call Count] END) AS total_rec
FROM Sched S LEFT JOIN
SchedTy T
ON S.schedTy_Id = T.id INNER JOIN
Events e
ON e.[Event Id] = s.id
WHERE [Call Count] > 0 AND
S.Status_id > 0 AND
e.DATE >= '2019-01-01' AND
e.DATE < '2020-01-01'
GROUP BY DatePart(Week, S.Date_)

How do I combine two columns into single column in static / dynamic pivot query using SQL Server

I have a schema like this
demo(month_year(navarchar), datecount(int), destination(nvarchar), type(nvarchar)).
In output i want to transform the rows to columns with concatenate columns.
datecount | Month_year | destination type
-------------------------+---------------+-------------------
07 | March - 18 | ABC No
23 | August - 2018 | ABC No
29 | August - 2018 | XYZ Sold Out
04 | July - 2018 | PQR Sold Out
10 | July - 2018 | XYZ No
25 | July - 2018 | ABC Sold Out
In the output i want,
Month_Year 1 2 3 ...
July - 2018 04(Sold Out-PQR) 10(No-XYZ) 25(Sold Out-ABC)
August - 2018 23(No-ABC) 29(Sold Out-XYZ)
I have tried more using the PIVOTE function. Facing the problem to display combination of datecount with destination and type as per above expected output. But could not get the solution. Please help me.
Just concatenate the values before pivoting.
;WITH ToPivot AS
(
SELECT
D.month_year,
ConcatenatedValues = CONVERT(VARCHAR(10), D.datecount) + '(' + D.type + '-' + D.destination + ')',
NumberToPivot = ROW_NUMBER() OVER (PARTITION BY D.month_year ORDER BY D.datecount ASC)
FROM
Demo AS D
)
SELECT
P.*
FROM
ToPivot AS T
PIVOT (
MAX(T.ConcatenatedValues)
FOR T.NumberToPivot IN (
[1], [2], [3], [4], [5], [6], [7], [8], [9], [10],
[11], [12], [13], [14], [15], [16], [17], [18], [19],
[20], [21], [22], [23], [24], [25], [26], [27], [28],
[29], [30], [31])
) AS P

SQL query get count item for report per day of the month?

i need sql query for report from table item per day(fix day1-day31 as column) of the month when i input month and year.
This is my table (item)
ID | NAME | DATE
---------------------------------------------------
1 | ITEM A | 2015-2-25 13:37:49
2 | ITEM A | 2015-2-25 14:37:49
3 | ITEM A | 2015-2-26 13:30:55
4 | ITEM B | 2015-2-26 15:37:49
5 | ITEM B | 2015-2-26 17:57:49
6 | ITEM C | 2015-2-27 13:00:33
(input month=02 and year=2015)
What I need to achieve with a view is the following:
NAME | 1| 2| 3|…|25|26|27|28|29|30|31|Total
------------------------------------------------------
ITEM A| 0| 0| 0|…| 2 | 1 | 0 | 0 | 0 | 0 | 0 | 3
ITEM B| 0| 0| 0|…| 0 | 2 | 0 | 0 | 0 | 0 | 0 | 2
ITEM C| 0| 0| 0|…| 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1
Any ideas would be very much appreciated.
Thanks in advance.
Sorry this is my first post.
You can do this using a PIVOT in your query
SELECT name,
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9],
[10],
[11],
[12],
[13],
[14],
[15],
[16],
[17],
[18],
[19],
[20],
[21],
[22],
[23],
[24],
[25],
[26],
[27],
[28],
[29],
[30],
[31],
([1] + [2] + [3] + [4] + [5] + [6] + [7] + [8] + [9] + [10] + [11] + [12] + [13] + [14] + [15] + [16] + [17] + [18] + [19] + [20] + [21] + [22] + [23] + [24] + [25] + [26] + [27] + [28] + [29] + [30] + [31]) as total
FROM
(
SELECT Name,
id,
Datepart(day, [date]) day
FROM item
WHERE MONTH([date]) = 2 AND YEAR([date]) = 2015
) x
PIVOT
(
count(id)
FOR day IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31])
) p
This will do it for you. First test data:
CREATE TABLE data ([ID] int, [Name] varchar(30), [Date] datetime)
INSERT INTO data ([ID], [Name], [Date])
SELECT 1,'ITEM A','2015-2-25 13:37:49'
UNION ALL SELECT 2,'ITEM A','2015-2-25 14:37:49'
UNION ALL SELECT 3,'ITEM A','2015-2-26 13:30:55'
UNION ALL SELECT 4,'ITEM B','2015-2-26 15:37:49'
UNION ALL SELECT 5,'ITEM B','2015-2-26 17:57:49'
UNION ALL SELECT 6,'ITEM C','2015-2-27 13:00:33'
Then the query. Note you can use any data range, so if you want a full month just calculate that and put it in the #startDate and #endDate
DECLARE #startDate DATETIME='25-Feb-2015'
DECLARE #endDate DATETIME='28-Feb-2015'
DECLARE #numberOfDays INT = DATEDIFF(DAY, #startDate, #endDate)
declare #dayColumns TABLE (delta int, colName varchar(12))
-- Produce 1 row for each day in the report. Note that this is limited by the
-- number of objects in sysobjects (which is about 2000 so its a high limit)
-- Each row contains a delta date offset, #startDate+delta gives each date to report
-- which is converted to a valid SQL column name in the format colYYYYMMDD
INSERT INTO #dayColumns (delta, colName)
SELECT delta, 'col'+CONVERT(varchar(12),DATEADD(day,delta,#startDate),112) as colName from (
select (ROW_NUMBER() OVER (ORDER BY sysobjects.id))-1 as delta FROM sysobjects
) daysAhead
WHERE delta<=#numberOfDays
-- Create a comma seperated list of columns to report
DECLARE #cols AS NVARCHAR(MAX)= ''
SELECT #cols=CASE WHEN #cols='' THEN #cols ELSE #cols+',' END + colName FROM #dayColumns ORDER BY delta
DECLARE #totalCount AS NVARCHAR(MAX)= ''
SELECT #totalCount=CASE WHEN #totalCount='' THEN '' ELSE #totalCount+' + ' END + 'ISNULL(' + colName +',0)' FROM #dayColumns ORDER BY delta
-- Produce a SQL statement which outputs a variable number of pivoted columns
DECLARE #query AS NVARCHAR(MAX)
SELECT #query=
'declare #days TABLE (reportDay date, colName varchar(12))
INSERT INTO #days (reportDay, colName)
SELECT DATEADD(day,Delta,'''+CONVERT(varchar(22),#startDate,121)+'''), ''col''+CONVERT(varchar(12),DATEADD(day,delta,'''+CONVERT(varchar(22),#startDate,121)+'''),112) as colName from (
select (ROW_NUMBER() OVER (ORDER BY sysobjects.id))-1 as Delta FROM sysobjects
) daysAhead
WHERE Delta<='+CAST(#numberOfDays as varchar(10))+'
SELECT pivoted.*,'+#totalCount+' as total FROM (
SELECT * FROM (
select data.Name, d.colName, 1 as numRows
from #days d
LEFT OUTER JOIN data ON CAST(data.[Date] as DATE)=d.reportDay
) as s
PIVOT (
SUM(numRows) FOR colName in ('+#cols+')
) as pa
) as pivoted
WHERE Name is not null'
-- Run the query
EXEC (#query)
Output is:
Name col20150225 col20150226 col20150227 col20150228 total
------------------------------ ----------- ----------- ----------- ----------- -----------
ITEM A 2 1 NULL NULL 3
ITEM B NULL 2 NULL NULL 2
ITEM C NULL NULL 1 NULL 1
You can determine the date of each column by parsing the column header in your presentation code (it's format is colYYYYMMDD).
select convert(varchar,PaymentDate,103) AS date,
DatePart(MONTH,PaymentDate) as month,
CAST(SUM(Total_Amount) as INT) as Revenue
from Tbl_Name
where YEAR(PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP)
GROUP BY convert(varchar,PaymentDate,103),
DatePart(MONTH,PaymentDate)
order by date;