Non Aggregate fields in MS SQL - sql-server

I have MS SQL server table which contains the data as follows
id val1 val2
1 100.00 50.00
2 25.00 30.00
3 30.00 25.00
4 100.00 50.00
5 40.00 80.00
6 25.00 30.00
7 80.00 21.00
8 25.00 30.00
In the above table, few val1 val2 values combination occurs more than ones i.e. 100.00 50.00 is occurred twice, 25.00 30.00 occurred thrice. Likewise, if any combinations occurred more than ones, I would need to get those Ids.
So my result would be id - 1,2,4,6,8.
please help how to query this in MS SQL. Thanks

The CTE obtains the val1, val2 pairs that occur more than once. The we join with the table to get the id values:
;with cte as (
select val1, val2
from t
group by val1, val2
having count(*) > 1
)
select id
from t
join cte on t.val1 = cte.val1 and t.val2 = cte.val2

Related

How to add values in sql

Hey i have a table like this
Product_name Rate Cost GST_percentage Recipt_no Amount Final_Amount ID Description GST_price Quantity OrderID Discount Net_Unit_Price Stock_Pending Payment_Pending
SINGTEL DATA + EZ $10 1.5 GB 7 DAYS 10 120.00 5 1 120.00 126 1 A 6.00 12 ODR1 0.00 10.00 Received Paid
SINGTEL DATA + EZ $10 1.5 GB 7 DAYS 12 180.00 0 2 180.00 180.00 2 A 0.00 15 ODR2 0.00 12.00 NULL NULL
SINGTEL DATA + EZ $8 CHINA 888 10 120.00 0 2 120.00 120.00 3 B 0.00 12 ODR2 0.00 10.00 NULL NULL
and i want to show the final_Amount column value groupped by order Id.then i want to show the final_amount for those which is Payment_Pending status is not null but i can't get the correct result.
Note:
i got a result as
query:
SELECT [OrderID],
SUM(convert(float,[Final_Amount])) as Final_Amount,
(select sum(convert(float,Final_Amount)) as Final_Amount
from Purchase_Order
where Payment_Pending is not null) as paid
FROM [Purchase_Order]
group by [OrderID]
order by OrderID desc
OrderID Final_Amount paid
ODR2 300 126
ODR1 126 126
but i want like this
OrderID Final_Amount paid
ODR2 300 0
ODR1 126 126
(Because ODR2 Payment_Pending Column filled with null)
Probably your sub-query is wrong. It need to include a reference to OrderId of main query
SELECT [OrderID],
SUM(convert(float,[Final_Amount])) as Final_Amount,
(select sum(convert(float,Final_Amount)) as Final_Amount
from Purchase_Order x
where x.Payment_Pending is not null
and x.OrderId = p.OrderId) as paid
FROM [Purchase_Order] p
group by [OrderID]
order by OrderID desc

Sql-Get time ranges from million+ rows for particular condition

I am working with SQL Server 2012, I have a table with approx 35 column and 10+ million rows.
I need to find time ranges from across the data where the value of any particular column is matching
E.g.
The sample data is as below
Datetime col1 col2 col3
2018-05-31 0:00 1 2 1
2018-05-31 13:00 2 2 2
2018-05-31 14:30 3 2 1
2018-05-31 15:00 4 3 1
2018-05-31 16:00 4 5 1
2018-05-31 17:00 3 2 2
2018-05-31 17:30 3 2 4
2018-05-31 18:00 2 2 4
2018-05-31 20:00 1 2 6
2018-05-31 21:00 2 2 3
2018-05-31 21:10 2 2 1
2018-05-31 22:00 1 6 3
2018-05-31 22:00 4 5 1
2018-05-31 23:59 4 7 2
Find the time range from data where col2 value =< 2, accordingly my expected result set is as below
Start Time End time Time Diff
2018-05-31 0:00 2018-05-31 14:30 14:30:00
2018-05-31 17:00 2018-05-31 21:10 4:10:00
I can achieved the same with below logic, but it's extremely slow
I get all rows and then
Order by date_Time
Scan the rows get the first row where exactly value is matching and record that timestamp as start time.
Scan further rows till i get the row where condition is breaking and record that timestamp as end time.
But as i have to play with huge no. Of rows, overall this will make my operation slow, any inputs or pseudo code to improve the same.
We can use a slightly modified difference in row number method here. The purpose of the first CTE labelled cte1 is to add a computed column which labels islands we want, having a col2 values <= 2, as 1 and everything else as 0. Then, we can compute the difference of two row numbers, and aggregate over the islands to find the starting and ending times, and the difference between those times.
WITH cte1 AS (
SELECT *,
CASE WHEN col2 <= 2 THEN 1 ELSE 0 END AS class
FROM yourTable
),
cte2 AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY Datetime) -
ROW_NUMBER() OVER (PARTITION BY class ORDER BY Datetime) rn
FROM cte1
)
SELECT
MIN(Datetime) AS [Start Time],
MAX(Datetime) AS [End Time],
CONVERT(TIME, MAX(Datetime) - MIN(Datetime)) AS [Time Diff]
FROM cte2
WHERE class = 1
GROUP BY rn
ORDER BY MIN(Datetime);
Demo

DateDiff of Logtable Dates Which Have The Same Column in SQL Server

Using SQL Server 2012 I need to get the datediff of all dates in a Log table which has the same column, for example:
ID | Version | Status | Date
-----------------------------------------------------
12345 | 1 | new | 2014-05-01 00:00:00.000
12345 | 2 | up | 2014-05-02 00:00:00.000
12345 | 3 | appr | 2014-05-03 00:00:00.000
67890 | 1 | new | 2014-05-04 00:00:00.000
67890 | 2 | up | 2014-05-08 00:00:00.000
67890 | 3 | rej | 2014-05-13 00:00:00.000
I need to get the date diff of all sequential dates (date between 1, 2 and date between 2, 3)
I have tried creating a while but with no luck!
Your help is really appreciated!
This Calculates DateDiff as per your query "date diff of all sequential dates",if not sequential,it will just show same date.Further please don't use Reserved Keywords as Column names
SELECT ID,
[VERSION],
[STATUS],
[DATE],
CASE WHEN LEAD([DATE]) OVER (PARTITION BY ID ORDER BY [VERSION])=DATEADD(DAY,1,[DATE])
THEN CAST(DATEDIFF(DAY,[DATE],LEAD([DATE]) OVER (PARTITION BY ID ORDER BY VERSION)) AS VARCHAR(5))
ELSE [DATE] END AS DATEDIFFF
FROM
#TEMP
Another way with OUTER APPLY (get the previous value) :
SELECT t.*,
DATEDIFF(day,p.[Date],t.[Date]) as dd
FROM YourTable t
OUTER APPLY (
SELECT TOP 1 *
FROM YourTable
WHERE ID = t.ID AND [DATE] < t.[Date] AND [Version] < t.[Version]
ORDER BY [Date] DESC
) as p
Output:
ID Version Status Date dd
12345 1 new 2014-05-01 00:00:00.000 NULL
12345 2 up 2014-05-02 00:00:00.000 1
12345 3 appr 2014-05-03 00:00:00.000 1
67890 1 new 2014-05-04 00:00:00.000 NULL
67890 2 up 2014-05-08 00:00:00.000 4
67890 3 rej 2014-05-13 00:00:00.000 5
Note: If you are using SQL Server 2012 then better use LEAD and LAG functions.

pivot table in TSQL

Here is the dataset from the table
TABLE XYZ
ID Date col1 col2 col3
1 2012-09-21 100.00 0.00 0.00
1 2012-09-21 0.00 10.00 20.00
2 2012-09-21 0.00 20.00 0.00
2 2012-09-21 100.00 0.00 20.00
3 2012-09-21 10.00 25.00 5.00
I want Result like below:
ID Date COL
1 2012-09-21 130.00
2 2012-09-21 140.00
3 2012-09-21 40.00
I tried below Query, but not getting a exact value from table.
Select ID,
date,
sum(Col1+col2+col3) as COL
From table xyz
Group by ID,DATE
I got below result set
ID Date COL
1 2012-09-21 130.00
2 2012-09-21 270.00
3 2012-09-21 310.00
IS there any better way to get expected result set or to do a pivot table?
Thanks
You can use CTE and then use group by on the result.
WITH S AS ( SELECT ID,DATE,COL1+COL2+COL3 AS. COLS FROM TABLE1);
SELECT ID,DATE,SUM(COLS)
FROM S
GROUP BY ID,DATE

T-SQL query update null values

I have a very specific problem in T-SQL.
If I can solve this example case I give you I think I will be able to solve my original case.
Having this data in a table:
DECLARE #Test TABLE
(
Value INT
,Date DATETIME2(7)
);
INSERT INTO #Test
VALUES
(NULL, '2011-01-01 10:00'),
(NULL, '2011-01-01 11:00'),
(2, '2011-01-01 12:00'),
(NULL, '2011-01-01 13:00'),
(3, '2011-01-01 14:00'),
(NULL, '2011-01-01 15:00'),
(NULL, '2011-01-01 16:00'),
(4, '2011-01-01 17:00'),
(NULL, '2011-01-01 18:00'),
(5, '2011-01-01 19:00'),
(6, '2011-01-01 20:00')
I need to select this output:
Value Date
2 2011-01-01 10:00
2 2011-01-01 11:00
2 2011-01-01 12:00
2 2011-01-01 13:00
3 2011-01-01 14:00
3 2011-01-01 15:00
3 2011-01-01 16:00
4 2011-01-01 17:00
4 2011-01-01 18:00
5 2011-01-01 19:00
6 2011-01-01 20:00
To give some explanation. If value is NULL somewhere I need to update with the value from the previous hour. If there are several null values in a row the closest earlier hour with a non null value propagates and fills all these null values. Also if the first hour of the day is null then the earliest hour on the day with a non null value propagates downwards like 2 in this case. In your case you can assume that at least one value is non null value.
My ambition is to solve this with Common table expressions or something similar. With the cursor way I think I would have the solution in short bit of time if I try but my attempts with CTEs and recursive CTEs have failed so far.
Since your condition is not always the same this is a little bit more difficult. In your example, the first two rows need to get their values from the first value with a later date, in the other cases they need to get the values from previous dates. If you would always need to look previous dates, you could simple do this query:
SELECT B.Value,
A.[Date]
FROM #Test A
OUTER APPLY (SELECT TOP 1 *
FROM #Test
WHERE [Date] <= A.[Date] AND Value IS NOT NULL
ORDER BY [Date] DESC) B
But in your case, I think that you need this instead:
SELECT ISNULL(B.Value,C.Value) Value,
A.[Date]
FROM #Test A
OUTER APPLY (SELECT TOP 1 *
FROM #Test
WHERE [Date] <= A.[Date] AND Value IS NOT NULL
ORDER BY [Date] DESC) B
OUTER APPLY (SELECT TOP 1 *
FROM #Test
WHERE Value IS NOT NULL
ORDER BY [Date]) C
try this:
select
t.value, t.date
,COALESCE(t.value
,(select MAX(tt.value) from #Test tt WHERE t.Date>tt.Date)
,(SELECT MIN(ttt.Value) FROM #Test ttt Where ttt.Date IS NOT NULL)
) AS UseValue
from #Test t
OUTPUT:
value date UseValue
----------- ----------------------- -----------
NULL 2011-01-01 10:00:00.000 2
NULL 2011-01-01 11:00:00.000 2
2 2011-01-01 12:00:00.000 2
NULL 2011-01-01 13:00:00.000 2
3 2011-01-01 14:00:00.000 3
NULL 2011-01-01 15:00:00.000 3
NULL 2011-01-01 16:00:00.000 3
4 2011-01-01 17:00:00.000 4
NULL 2011-01-01 18:00:00.000 4
5 2011-01-01 19:00:00.000 5
6 2011-01-01 20:00:00.000 6

Resources