I am having an issue and I have been working on it for the past three hours or so and have not found a solution. Running on a SQL Server platform. I have a single table that looks like this.
PT ITM VAL
-- --- ---
01 01 A
01 02 B
01 03 C
02 01 A
02 03 C
03 01 A
03 02 B
I am trying to find which PTs are missing the item numbers.
In the case above PT02 and PT03 are missing two item. This is the base what where I started, but I am not sure if I am even on the right track.
select t.PT,t.ITM
FROM MYTABLE t
GROUP BY t.PT,t.ITM
HAVING COUNT(*) > 1
Thanks
jlimited
If you're expecting 3 ITM per PT, the query would be
select PT
FROM MYTABLE
GROUP BY PT
HAVING COUNT(ITM) < 3
for other conditions a more complicated query is required.
Here was the solution that worked. I had to select a VAL that was populated, to find the values that were not.
select stg.PT,COUNT(stg.ITM) AS ITM_CNT
FROM MYTABLE stg
WHERE stg.ITM IS NOT NULL
AND stg.VAL IN (11)
GROUP BY stg.PT
HAVING COUNT(stg.ITM) > 1
EXCEPT
select stg.PT,COUNT(stg.ITM) AS ITM_CNT
FROM MYTABLE stg
WHERE stg.ITM IS NOT NULL
AND stg.VLA IN (4,5)
GROUP BY stg.PT
HAVING COUNT(stg.ITM) > 1
Related
I need to convert Column and a row into 2 columns.
Below is the sample Table [Table01] with 4 columns and a single row.
First Second Third Forth
01 02 03 04
I need to Transpose it as a new table [Table01_T]
Column01 Column02
First 01
Second 02
Third 03
Forth 04
Every time we receive a single row with 4 columns and we need them to convert in 2 columns and four rows.
Something like this
select
v.*
from [Table01]
cross apply
(values ('First', [First]),('Second',[Second]),
('Third',[Third]),('Forth',[Forth])) v(Column01, Column02);
Using the same sample data this query produces the same results. I find this syntax to be more readable then UNPIVOT.
Results
Column1 Column02
First 01
Second 02
Third 03
Forth 04
You can use UNPIVOT:
SELECT Column01, Column02
-- INTO dbo.Table01_T
FROM dbo.Table01
UNPIVOT
( -- vvvvv column names you want to turn to rows
Column02 FOR Column01 IN ([First],[Second],[Third],[Fourth])
-- ^^^^^^^^ becomes column name from each original column
-- ^^^^^^^^ becomes column value from each original column
) AS u;
Isolated example using a table variable:
DECLARE #x table([First] char(2),Second char(2),Third char(2),Fourth char(2));
INSERT #x([First],[Second],[Third],[Fourth]) VALUES ('01','02','03','04');
SELECT Column01, Column02
FROM #x UNPIVOT
(
Column02 FOR Column01 IN ([First],[Second],[Third],[Fourth])
) AS u;
Results:
Column01 Column02
-------- --------
First 01
Second 02
Third 03
Fourth 04
Working fiddle
I have two tables in SQL that look like this:
Table 1:
ID TaxYear Earnings
01 2000 2234
01 2001 123
02 2004 12344
02 2006 234
02 2007 0
02 2008 123
Table 2:
ID JobEnd
01 1998
02 2000
02 2007
I need to combine these tables to make a new column giving the number of years between TaxYear and JobEnd. However, I need this value to reset every time TaxYear passes a new JobEnd year. So my final table would look like this:
ID TaxYear Earnings YearsSinceJobEnd
01 2000 2234 2
01 2001 123 3
02 2004 12344 4
02 2006 234 6
02 2007 0 7
02 2008 123 1
For ID 02, when YearsSinceJobEnd is calculated as TaxYear minus 2000, up until TaxYear passes the new JobEnd year of 2007, when it is subsequently calculated as TaxYear minus 2007.
I'm getting very confused about how to do this. If I join the tables I end up with multiple columns per TaxYear, which I need to avoid. But I can't think how to calculate the new column without joining them.
Any help would be much appreciated.
You can use datediff() with DATETIMEFROMPARTS ():
select t1.id, t1.TaxYear, t1.Earnings,
datediff(year, DATEFROMPARTS(t2.JobEnd, 1, 1), DATEFROMPARTS(t1.TaxYear, 1, 1)) as YearsSinceJobEnd
from t1 inner join
t2
on t2.id = t1.id;
If you don't want JOIN then use APPLY :
select t1.id, t1.TaxYear, t1.Earnings,
datediff(year, DATEFROMPARTS(t2.JobEnd, 1, 1), DATEFROMPARTS(t1.TaxYear, 1, 1)) as YearsSinceJobEnd
from t1 cross apply
( select top (1) t2.JobEnd
from t2
where t2.id = t1.id and t2.JobEnd < t1.TaxYear
order by t2.JobEnd desc
) t2;
you can user CROSS APPLY to find the required JobEnd for each ID
SELECT t1.ID, t1.TaxYear, t1.Earnings,
YearsSinceJobEnd = t1.TaxYear - e.JobEnd
FROM Table1 t1
CROSS APPLY
(
SELECT JobEnd = MAX(t2.JobEnd)
FROM Table2 t2
WHERE t2.ID = t1.ID
AND t2.JobEnd < t1.TaxYear
) e
Can anyone help me to calculate the time difference(in hh:mm) between the two rows, when the Procs_ID changes from 01 to another Procs_ID.
Procs_ID meter_id date
01 0000012 2015-10-12 09:07:22.530
03 0000013 2015-10-12 09:11:51.733
01 0000014 2015-10-12 09:12:38.550
02 0000015 2015-10-12 10:38:52.923
03 0000016 2015-10-12 10:40:33.467
01 0000017 2015-10-12 10:40:56.013
Thanks in advance
Here is an example with LEAD which is avaliable for SQL Server 2012+
select
*,
case
when Procs_Id = '01'
and lead(Procs_ID) over (order by [date]) <> Procs_ID then datediff(mi,[date],lead([date]) over (order by [date]))
end as TimeDiffInMin
from YourTable
Am wondering how to write a stored procedure to aggregate the rows in the data.
Sample data:
Start End id
1 2 01
2 3 01
3 0 01
3 4 02
4 7 02
In this I should merge the rows with the same id of the sequential rows and start attribute of beginning row is less than end value of the last row. Also should store them in a table
Output of sample input:
Start End id
1 3 01
3 0 01
3 7 02
The logic is failing with the procedure I wrote.
Assuming that your data is good (no gaps in start/end):
select MIN(Start) [Start],
MAX(End) [End],
id
from YourTable
group by id
I have the following SQL Server 2008 table:
ID Destination Last Result
01 (555) 319-5170 Disconnect
02 (555) 319-5170 Duplicate
03 (555) 319-5170 Duplicate
04 (555) 261-5000 Duplicate
05 (555) 261-5000 Duplicate
06 (555) 261-7325 Busy
07 (555) 261-7325 Duplicate
08 (555) 261-7345 No Answer
09 (555) 261-7345 Duplicate
My goal is to dynamically set the 'Last Result' column for all matching phone numbers. So, in the example table above for Destination((555) 319-5170), the result for all matching phone numbers(555) 319-5170) with the value 'Disconnect'. The sample update statement is below:
UPDATE C
SET [Last Result] = (
SELECT Destination
FROM Call
WHERE [Last Result] NOT IN ('Duplicate','No Phone #')
GROUP BY Destination
HAVING COUNT(Destination) > 1)
FROM Call C
INNER JOIN
(
SELECT Destination
FROM Call
WHERE [Last Result] NOT IN ('Duplicate','No Phone #')
GROUP BY Destination
HAVING COUNT(Destination) > 1
) Dup ON Dup.Destination = C.Destination
WHERE C.[Last Result] NOT IN ('Duplicate','No Phone #')
But I am getting an error:
Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
**EXPECTED OUTPUT**:
ID Destination Last Result
01 (555) 319-5170 Disconnect
02 (555) 319-5170 Disconnect
03 (555) 319-5170 Disconnect
04 (555) 261-5000 Duplicate
05 (555) 261-5000 Duplicate
06 (555) 261-7325 Busy
07 (555) 261-7325 Busy
08 (555) 261-7345 No Answer
09 (555) 261-7345 No Answer
Thanks in advance for any assistance with a possible solution.
You can look up the first Last Result with the row_number() window function. However, there has to be a way to define "first". In the example, I'm assuming you have an identity column:
update t1
set [Last Result] = t2.[Last Result]
from Table1 t1
join (
select row_number() over (partition by Destination
order by Id) as rn
, *
from Table1
) t2
on t1.Destination = t2.Destination
and t2.rn = 1;
Example at SQL Fiddle.
If you do not have an identity column, please update the question with how you define "first". There could be a CreateDt column for example.