SQL select values sum same ID - sql

This is my Table called "SAM"
ID | S_Date | S_MK | TID | Value |
===============================================
1 | 2012-12-11 | 1 | 112 | 23 |
2 | 2012-12-11 | 2 | 112 | 3 |
3 | 2012-12-11 | 1 | 113 | 22 |
4 | 2012-12-11 | 3 | 114 | 2 |
This should be my expected result: sum of column "Value" with the same T_ID:
S_Date | TID | sum(Value)|
===============================
2012-12-11 | 112 | 26 |
2012-12-11 | 113 | 22 |
2012-12-11 | 114 | 2 |

select S_Date, TID, sum(Value)
from SAM
group by S_Date, TID

If you really need this result set, with grouping only by T_ID, you can use this query:
SELECT (SELECT top 1 S_Date FROM SAM as t1 WHERE t1.TID = t2.TID) as S_Date,
TID,
SUM(Value)
FROM SAM as t2
GROUP BY TID

You have to use aggregate function "sum" for the sum of value column.
select S_Date ,TID, Sum(Value) from Sam group by S_Date, TID
Further more you should include all the column in group by clause that you used in select statement.

SELECT *, SUM(Value) AS Value From SAM GROUP BY TID
This will return the same table by summing up the Value column of the same TID column.

Related

SQL group by changing column

Suppose I have a table sorted by date as so:
+-------------+--------+
| DATE | VALUE |
+-------------+--------+
| 01-09-2020 | 5 |
| 01-15-2020 | 5 |
| 01-17-2020 | 5 |
| 02-03-2020 | 8 |
| 02-13-2020 | 8 |
| 02-20-2020 | 8 |
| 02-23-2020 | 5 |
| 02-25-2020 | 5 |
| 02-28-2020 | 3 |
| 03-13-2020 | 3 |
| 03-18-2020 | 3 |
+-------------+--------+
I want to group by changes in value within that given date range, and add a value that increments each time as an added column to denote that.
I have tried a number of different things, such as using the lag function:
SELECT value, value - lag(value) over (order by date) as count
GROUP BY value
In short, I want to take the table above and have it look like:
+-------------+--------+-------+
| DATE | VALUE | COUNT |
+-------------+--------+-------+
| 01-09-2020 | 5 | 1 |
| 01-15-2020 | 5 | 1 |
| 01-17-2020 | 5 | 1 |
| 02-03-2020 | 8 | 2 |
| 02-13-2020 | 8 | 2 |
| 02-20-2020 | 8 | 2 |
| 02-23-2020 | 5 | 3 |
| 02-25-2020 | 5 | 3 |
| 02-28-2020 | 3 | 4 |
| 03-13-2020 | 3 | 4 |
| 03-18-2020 | 3 | 4 |
+-------------+--------+-------+
I want to eventually have it all in one small table with the earliest date for each.
+-------------+--------+-------+
| DATE | VALUE | COUNT |
+-------------+--------+-------+
| 01-09-2020 | 5 | 1 |
| 02-03-2020 | 8 | 2 |
| 02-23-2020 | 5 | 3 |
| 02-28-2020 | 3 | 4 |
+-------------+--------+-------+
Any help would be very appreciated
you can use a combination of Row_number and Dense_rank functions to get the required results like below:
;with cte
as
(
select t.DATE,t.VALUE
,Dense_rank() over(partition by t.VALUE order by t.DATE) as d_rank
,Row_number() over(partition by t.VALUE order by t.DATE) as r_num
from table t
)
Select t.Date,t.Value,d_rank as count
from cte
where r_num = 1
You can use a lag and cumulative sum and a subquery:
SELECT value,
SUM(CASE WHEN prev_value = value THEN 0 ELSE 1 END) OVER (ORDER BY date)
FROM (SELECT t.*, LAG(value) OVER (ORDER BY date) as prev_value
FROM t
) t
Here is a db<>fiddle.
You can recursively use lag() and then row_number() analytic functions :
WITH t2 AS
(
SELECT LAG(value,1,value-1) OVER (ORDER BY date) as lg,
t.*
FROM t
)
SELECT t2.date,t2.value, ROW_NUMBER() OVER (ORDER BY t2.date) as count
FROM t2
WHERE value - lg != 0
Demo
and filter through inequalities among the returned values from those functions.

How to sum rows before a condition is met in SQL

I have a table which has multiple records for the same id. Looks like this, and the rows are sorted by sequence number.
+----+--------+----------+----------+
| id | result | duration | sequence |
+----+--------+----------+----------+
| 1 | 12 | 7254 | 1 |
+----+--------+----------+----------+
| 1 | 12 | 2333 | 2 |
+----+--------+----------+----------+
| 1 | 11 | 1000 | 3 |
+----+--------+----------+----------+
| 1 | 6 | 5 | 4 |
+----+--------+----------+----------+
| 1 | 3 | 20 | 5 |
+----+--------+----------+----------+
| 2 | 1 | 230 | 1 |
+----+--------+----------+----------+
| 2 | 9 | 10 | 2 |
+----+--------+----------+----------+
| 2 | 6 | 0 | 3 |
+----+--------+----------+----------+
| 2 | 1 | 5 | 4 |
+----+--------+----------+----------+
| 2 | 12 | 3 | 5 |
+----+--------+----------+----------+
E.g. for id=1, i would like to sum the duration for all the rows before and include result=6, which is 7254+2333+1000+5. Same for id =2, it would be 230+10+0. Anything after the row where result=6 will be left out.
My expected output:
+----+----------+
| id | duration |
+----+----------+
| 1 | 10592 |
+----+----------+
| 2 | 240 |
+----+----------+
The sequence has to be in ascending order.
I'm not sure how I can do this in sql.
Thank you in advance!
I think you want:
select t2.id, sum(t2.duration)
from t
where t.sequence <= (select t2.sequence
from t t2
where t2.id = t.id and t2.result = 6
);
In PrestoDB, I would recommend window functions:
select id, sum(duration)
from (select t.*,
min(case when result = 6 then sequence end) over (partition by id) as sequence_6
from t
) t
where sequence <= sequence_6;
You can use a simple aggregate query with a condition that uses a subquery to recover the sequence corresponding to the record whose sequence is 6 :
SELECT t.id, SUM(t.duration) total_duration
FROM mytable t
WHERE t.sequence <= (
SELECT sequence
FROM mytable
WHERE id = t.id AND result = 6
)
GROUP BY t.id
This demo on DB Fiddle with your test data returns :
| id | total_duration |
| --- | -------------- |
| 1 | 10592 |
| 2 | 240 |
Basic group by query should solve your issue
select
id,
sum(duration) duration
from t
group by id
for the certain rows:
select
id,
sum(duration) duration
from t
where id = 1
group by id
if you want to include it in your result set
select id, duration, sequence from t
union all
select
id,
sum(duration) duration
null sequence
from t
group by id

SQLite: average of column indexed by two columns

Given the following table
+----+----+------+
|id1 |id2 |value |
+----+----+------+
| 1 | 2 | 10 |
| 1 | 3 | 20 |
| 1 | 4 | 30 |
| 2 | 3 | 10 |
| 2 | 4 | 40 |
| 3 | 4 | 10 |
+----+----+------+
I want to have avg(value) of each id, whether located the id1 or id2 column.
Thus, the output should be:
1,20
2,20
3,16.66
4,26.6
Help would be greatly appreciated.
You could use UNION ALL:
WITH cte AS (
SELECT id, value FROM tab
UNION ALL
SELECT id2, value FROM tab
)
SELECT id, AVG(value) AS value
FROM cte
GROUP BY id;
DBFidde Demo

Select most recent inspection

I have a ROAD_INSPECTION table:
+----+------------------------+-----------+
| ID | DATE | CONDITION |
+----+------------------------+-----------+
| 1 | 01/01/2009 | 20 |
| 1 | 05/01/2013 | 16 |
| 1 | 04/29/2016 10:02:52 AM | 15 |
+----+------------------------+-----------+
| 2 | 01/01/2009 | 8 |
| 2 | 06/06/2012 9:55:13 AM | 8 |
| 2 | 04/28/2015 | 11 |
+----+------------------------+-----------+
| 3 | 06/11/2012 | 10 |
| 3 | 04/21/2015 | 19 |
+----+------------------------+-----------+
What is the most efficient way to select the most recent inspection? The query would need to include the ID and CONDITION columns, despite the fact that they wouldn't group by cleanly:
+----+------------------------+-----------+
| ID | DATE | CONDITION |
+----+------------------------+-----------+
| 1 | 04/29/2016 10:02:52 AM | 15 |
+----+------------------------+-----------+
| 2 | 04/28/2015 | 11 |
+----+------------------------+-----------+
| 3 | 04/21/2015 | 19 |
+----+------------------------+-----------+
One way could be to retrieve id and date column in derived table and join the output to the main table to retrieve corresponding data from condition column as below.
SELECT t1.id,
t1.date1,
t2.CONDITION1
FROM
(SELECT id,
max(date1) AS date1
FROM table1
GROUP BY id) t1
JOIN table1 t2 ON t1.id = t2.id
AND t1.date1 = t2.date1;
Result:
id date1 CONDITION1
-------------------------------------
1 29.04.2016 10:02:52 15
2 28.04.2015 00:00:00 11
3 21.04.2015 00:00:00 19
DEMO
OR if your rdbms supports windows function, use below.
SELECT id,
date1,
condition1
FROM
(SELECT id,
date1,
condition1,
row_number() over(PARTITION BY id
ORDER BY date1 DESC) AS rn
FROM table1 ) t1
WHERE rn = 1;
DEMO

How do I select each data set from a Row_Number Over Partition by table based on the Row_Number Over Partition by column?

How do I select each data set from a Row_Number Over Partition by table based on the Row_Number Over Partition by column?
please diagram below:
+-----------+-------------+-------------------+------------+----------+
| packageid | packagename | package max units | references | row_Numb |
+-----------+-------------+-------------------+------------+----------+
| 44 | Basic | 10 | 103 | 1 |
| 45 | Basic | 10 | 103 | 2 |
| 42 | Cola | 10 | 102 | 1 |
| 43 | Cola | 10 | 102 | 2 |
| 46 | Cola | 10 | 102 | 3 |
| 2 | Home | 11 | 101 | 1 |
| 11 | Home | 11 | 101 | 2 |
| 21 | Home | 11 | 101 | 3 |
| 1 | Spicy | 11 | 104 | 1 |
| 3 | Spicy | 11 | 104 | 2 |
| 41 | Spicy | 11 | 104 | 3 |
+-----------+-------------+-------------------+------------+----------+
I want select each data set in each group based on the row_num column.
Every attempt is welcomed.
Although it sounds like you already have the ROW_NUMBER() column, I believe it is what you are asking for . For the first record for each PACKAGENAME use:
SELECT s.* FROM (
SELECT t.*,
ROW_NUMBER() OVER(PARTITION BY t.packagename ORDER BY t.packageid) as rnk
FROM YourTable t) s
WHERE s.rnk = 1
For all of them use only the inner query.
Here is the cte version, if you want to fetch single record from each group.
;with cte_1
as(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY [packagename],[package max units], [references] ORDER BY [packageid]) as row_Numb
FROM YourTable )
SELECT [packageid],[packagename],[package max units],[reference]
FROM cte_1
WHERE row_Numb = 1
You can use TOP 1 WITH TIES with ordering by ROW_NUMBER():
SELECT TOP 1 WITH TIES *
FROM YourTable
ORDER BY ROW_NUMBER() OVER (PARTITION BY packagename ORDER BY packageid)
Output:
packageid packagename package max units references
44 Basic 10 103
42 Cola 10 102
2 Home 11 101
1 Spicy 11 104