I need to unpivot this table using T-SQL in SSMS. I don't need to aggregate anything and I am not able to predict the update dates for each ticket. I am using row_number() over partition by to force the sort in the first table and I need to maintain the horizontal sort of dates by ticket in the desired table.
Does anyone have any ideas on how to do this?
Change this table:
rownum
ticket
updated
1
1
1/1/2022
2
1
1/3/2022
1
2
1/27/2022
1
3
3/1/2022
2
3
4/2/2022
3
3
3/1/2022
1
4
7/11/2022
to this table:
ticket
Dt1
Dt2
Dt3
1
1/1/2022
1/3/2022
2
1/27/2022
3
3/1/2022
4/2/2022
5/3/2022
4
7/11/2022
SELECT ticket,
[dt1],
[dt2],
[dt3]
FROM (SELECT ticket,
Concat('DT', rownum) AS Col,
updated
FROM TEST) Src
PIVOT ( Max(updated)
FOR col IN ( [DT1],
[DT2],
[DT3] ) ) Pvt
dbfiddle
I am stuck with a problem.
I have some data likes these :
Id Creation date Creation date hour range Id vehicule Id variable Value
1 2017-03-01 9:10 2017-03-01 9:00 1 6 0.18
2 2017-03-01 9:50 2017-03-01 9:00 1 3 0.50
3 2017-03-01 9:27 2017-03-01 9:00 1 3 null
4 2017-03-01 10:05 2017-03-01 10:00 1 3 0.35
5 2017-03-01 10:17 2017-03-01 10:00 1 3 0.12
6 2017-03-01 9:05 2017-03-01 9:00 1 5 0.04
7 2017-03-01 9:57 2017-03-01 9:00 1 5 null
I need to select rowset group by Id vehicule, Id variable, Creation date hour range and order by group by Id vehicule, Id variable, Creation date where the first Value is null but second value, third value, ... is not null. So, in the sample above, the following rowset :
Id Creation date Creation date hour range Id vehicule Id variable Value
3 2017-03-01 9:27 2017-03-01 9:00 1 3 null
2 2017-03-01 9:50 2017-03-01 9:00 1 3 0.50
Could you help me please ?
Thank you
You will have no luck with a group by in this case. I would give 2 "if exists" into the where clause to filter all IDs that fit your criteria:
(for example/not tested/probably takes forever)
select *
from yourTable y1
where id in
--the id must be in all IDs, where the first value of the set is null
--same ID instead of group by
(select 1 from yourTable y2 where y1.IDs = y2.IDs and
--the first in the set
y2.createdate = (select min(createdate) from yourtable y3 with sameid) and
y2.value is null)
AND
--the id must also be in the IDs, where there are values besides the first that are not null
id in (same select but with "not min" and "not null" obviously
hope that helped :)
Include the Value field in the ORDER BY clause and it will be sorted to the top because NULL has a lower practical value than a non-NULL value.
Assuming (because your middle paragraph is hard to understand) you want all the fields output but you want the 4th and 5th columns to produce some grouping of the output, with Value = NULL at the top of each group:
SELECT Id, CreatedDate, CreatedDateHourRange, IdVehicule, IdVariable, Value
ORDER BY IdVehicule, IdVariable, Value
I don't see any need for an actual GROUP BY clause.
I think it is unclear as to whether you want to limit the NULL Value rows in each block to just one row of NULL, but if you do you would need to state the order for which the datetime columns are sorted.
indeed group by was no use here. Also I wasn't sure where your 10:00 records were going to. Does this help?
;WITH CTE_ADD_SOME_LOGIC
AS
(
SELECT Id, CreationDate ,CreationDateHourRange ,IdVehicle ,IdVariable ,Value
, CASE WHEN Value IS NULL THEN 1 ELSE 0 END AS VALUE_IS_NULL FROM tbl
),
CTE_MORE_LOGIC
AS
(
SELECT Id, CreationDate ,CreationDateHourRange ,IdVehicle ,IdVariable ,Value,VALUE_IS_NULL
, RANK() OVER (ORDER BY CreationDateHourRange,VALUE_IS_NULL) AS RN FROM CTE_ADD_SOME_LOGIC),
CTE_ORDER
AS
(
SELECT Id, CreationDate ,CreationDateHourRange ,IdVehicle ,IdVariable ,Value,VALUE_IS_NULL, RN
, ROW_NUMBER() OVER(PARTITION BY RN ORDER BY RN,IdVehicle,IdVariable,CreationDate, VALUE_IS_NULL DESC) AS HIERARCHY FROM CTE_MORE_LOGIC
)
SELECT Id, CreationDate ,CreationDateHourRange ,IdVehicle ,IdVariable ,Value FROM CTE_ORDER WHERE HIERARCHY = 1
ORDER BY Id
Try this Query
DECLARE #Nulloccurrence INT=1 -- Give like 1,2,3 value to get first null occurrence 2 for 2nd null occurrence
SELECT TOP 2 *
FROM cte
WHERE Id <= (
SELECT ID FROM
(
SELECT Id, ROW_NUMBER()OVER( Order by id) AS Seq
FROM cte
WHERE (
CASE
WHEN CAST(variableValue AS VARCHAR) IS NULL
THEN 'P'
ELSE CAST(variableValue AS VARCHAR)
END
) = 'P'
)Dt
WHERE Dt.Seq=#Nulloccurrence
)
ORDER BY 1 DESC
Expected Result
Id Creationdate Creationdatehourrange Ids vehicleId variableValue
------------------------------------------------------------------------
3 2017-03-01 9:27 2017-03-01 9:00 1 3 NULL
2 2017-03-01 9:50 2017-03-01 9:00 1 3 0.50
For 'where the first Value is null but second value, third value, ... is not null' i suppose you want to filter cases where there is a null and a not null value at [Value] within the set you group by, to decide to filter or not that grouped row. This cannot be filtered on standard WHERE clause because at WHERE clause each row is filtered with conditions relevant to that row scope only. Simply put, each row filtered cannot 'see' other rows unless you use sub-query. You need to use HAVING clause (the comment out is for 2+ null records)
This will work:
> DECLARE #mytbl TABLE(Id INT, [Creation date] DATETIME, [Creation date
> hour range] DATETIME, [Id veh] INT, [Id var] INT, Value INT )
>
> INSERT INTO #mytbl VALUES (1,'2017-03-01 9:10 ','2017-03-01 9:00 ',1,
> 6, 0.18) INSERT INTO #mytbl VALUES (2,'2017-03-01 9:50 ','2017-03-01
> 9:00 ',1, 3, 0.50) INSERT INTO #mytbl VALUES (3,'2017-03-01 9:27
> ','2017-03-01 9:00 ',1, 3, NULL) INSERT INTO #mytbl VALUES
> (4,'2017-03-01 10:05','2017-03-01 10:00',1, 3, 0.35) INSERT INTO
> #mytbl VALUES (5,'2017-03-01 10:17','2017-03-01 10:00',1, 3, 0.12)
> INSERT INTO #mytbl VALUES (6,'2017-03-01 9:05 ','2017-03-01 9:00 ',1,
> 5, 0.04) INSERT INTO #mytbl VALUES (7,'2017-03-01 9:57 ','2017-03-01
> 9:00 ',1, 5, NULL)
>
> SELECT [Id veh], [Id var],[Creation date hour range] FROM #mytbl GROUP
> BY [Id veh], [Id var],[Creation date hour range] HAVING COUNT([Id
> veh]) - COUNT(Value) = 1
> --HAVING COUNT([Id veh]) - COUNT(Value) >= 1 ORDER BY [Id veh], [Id var],[Creation date hour range]
Please find below input and required output. i need a query/procedure/function in T-SQL to get this output.
Requirement: I have table a and table b.
get all the date ranges from table b and missing date ranges from table a (when compared with table b).
Basically we need to make sure all the date ranges in table a, need to be covered in the output
Input
table b
Start date End date ID
1/1/2009 9/30/2009 1
1/1/2013 9/30/2013 1
11/1/2014 11/30/2014 1
2/2/2015 12/31/2016 1
table a
1/1/2009 12/31/2011 1
1/1/2013 9/30/2013 1
1/1/2014 4/30/2014 1
10/1/2014 12/31/2014 1
2/2/2015 12/31/9999 1
Output
table b
Start date End date ID
1/1/2009 9/30/2009 1
1/1/2013 9/30/2013 1
11/1/2014 11/30/2014 1
2/2/2015 12/31/2016 1
table a
10/1/2009 12/31/2011 1
1/1/2014 4/30/2014 1
10/1/2014 10/31/2014 1
12/1/2014 12/31/2014 1
1/1/2017 12/31/9999 1
Table [a] contain 4 records and table[b] contain 5 records. And you need that 5th record to be inserted into table [b]. If this is correct then...
Do simple outer join on table [a] and [b] on start data and end data. Get the value from table [a] where you find respective row NULL in table [b]
seems simple as it is :-)
Happy coding!!!
I have below tables structures,
Trans Table:
Trans_Id(PK) User_Id(FK) Arroved_Date
________________________________________________
1 101 05-06-2016
2 101 12-06-2016
3 101 20-06-2016
4 102 06-06-2016
5 103 10-06-2016
6 103 25-06-2016
Table2:
Id(Pk) User_Id(Fk) Start_Date End_Date Is_Revoked
_________________________________________________________________________
1 101 01-06-2016 15-06-2016 1
2 101 10-06-2016 15-06-2016 0
3 103 05-06-2016 20-06-2016 0
I want to filter out the transaction, if the Approved_Date is not between the users Start_Date and End_Date of table2.
If is_revoked = 1 then it should not consider.
Expected Result:
Trans_Id
________
1
3
4
6
Try this
SELECT A.Trans_ID
FROM TransTable A JOIN Table2 B
ON (A.User_Id = B.User_Id)
WHERE B.Is_Revoked = 1 OR A.Approved_Date NOT BETWEEN B.Start_Date AND B.End_Date
This resolves you,
SELECT Trans_Id FROM TRANS AS A JOIN TABLE2 AS B ON A.[USER_ID]=B.[USER_ID]
WHERE B.IS_REVOKED=0 AND ARROVED_DATE NOT BETWEEN B.START_DATE AND B.END_DATE
there are basically two condition you want to meet.
if is_revoked is equal to 1 then ignore the row from the result..
if Approved_Date is between start_date and end_date then dont consider then also ignore this from the result.
So this can be easily done using join.
SELECT A.Trans_ID
FROM TransTable A, Table2 B
WHERE B.Is_Revoked != 1 AND A.Approved_Date NOT BETWEEN B.Start_Date AND
B.End_Date
As far as I understand from the expected result that you mentioned. you really dont' care if the User_id matches or not.
Need help with this.
I have this table of data for illustration. (There are many other rows of data with different customer. Do consider this in the answer)
RowID Customer Category Date Figure1
1 Cust1 Week 1 Jun-11 10
2 Cust1 Week 2 Jun-11 20
3 Cust1 Week 3 Jun-11 30
4 Cust1 Week 4 Jun-11 40
5 Cust1 Actual Jun-11 200
6 Cust1 Forecast Jun-11 100
7 Cust2 Forecast Jun-11 100
I would like to have it display the Category Actual only (row 5) including the RowID on the pivoted Category as shown below
This should be the output.
RowID Customer Date Week1 Week2 Week3 Week4 Actual Forecast
5 Cust1 Jun-11 10 20 30 40 200 100
Any help would be appreciated.
Thanks in advance.
Tried Pivot but it gives me this which is not i want.
RowID Customer Date Week1 Week2 Week3 Week4 Actual Forecast
1 Cust1 Jun-11 10 null null null null null
2 Cust1 Jun-11 null 20 null null null null
3 Cust1 Jun-11 null null 30 null null null
4 Cust1 Jun-11 null null null 40 null null
5 Cust1 Jun-11 null null null null 200 null
6 Cust1 Jun-11 null null null null null 100
PIVOT is fine, but you need to GROUP BY and SUM afterwards.
Alternatively, you can self-JOIN on all the different code criteria, but it can be slightly less-maintainable than having the list of values in one place like you can with PIVOT.
You could do it this way:
SELECT
RowID,
Customer,
Date,
(SELECT Figure1 FROM sotest WHERE Customer = 'Cust1' AND Date = 'Jun-11' AND Category = 'Week 1') AS Week1,
(SELECT Figure1 FROM sotest WHERE Customer = 'Cust1' AND Date = 'Jun-11' AND Category = 'Week 2') AS Week2,
(SELECT Figure1 FROM sotest WHERE Customer = 'Cust1' AND Date = 'Jun-11' AND Category = 'Week 3') AS Week3,
(SELECT Figure1 FROM sotest WHERE Customer = 'Cust1' AND Date = 'Jun-11' AND Category = 'Week 4') AS Week4,
(SELECT Figure1 FROM sotest WHERE Customer = 'Cust1' AND Date = 'Jun-11' AND Category = 'Actual') AS Actual,
(SELECT Figure1 FROM sotest WHERE Customer = 'Cust1' AND Date = 'Jun-11' AND Category = 'Forecast') AS Forecast
FROM
sotest
WHERE
Customer = 'Cust1'
AND Date = 'Jun-11'
AND Category = 'Actual'
Should be fairly easy to wrap up in a stored procedure, where you can pass the CustomerID and Date params in.
Try this solution based on two parameters (#MyCustomer & #MyDate):
DECLARE #MyCustomer VARCHAR(10) = 'Cust1'
,#MyDate VARCHAR(10) = 'Jun-11';
SELECT pvt.*
FROM
(
SELECT t.Customer, t.Date, t.Category, t.Figure1
FROM MyTable t
WHERE t.Customer = #MyCustomer AND t.[Date] = #MyDaye
) src
PIVOT ( SUM(src.Figure1) FOR src.Category IN ([Week 1], [Week 2], [Week 3], [Week 4], [Actual], [Forecast]) ) pvt
The basic idea is to filter in src derived table only those rows and columns you need for pivot, nothing more or less.