Select last ten items from a specific row in a table - sql

I think this should be a pretty simple question to people who have some experience with database queries
I have a table
Line_ID Run_Date Product_ID Pallet_Cd Run_Qty
1 2012-10-31 01:00:00.000 175 00801004718000000002 0
1 2012-11-28 12:38:01.340 6 00801004718000000003 72
1 2012-11-28 13:32:25.250 4 00801004718000000004 180
1 2012-11-28 17:03:30.937 8 00801004718000000005 72
1 2012-11-29 07:29:58.603 1 00801004718000000006 120
1 2012-11-29 08:03:10.597 6 00801004718000000007 72
1 2012-11-29 08:24:11.370 4 00801004718000000008 180
1 2012-11-30 11:21:56.253 6 00801004718000000009 72
please excuse the formatting but hopefully you can see what the table is supposed to be.
I want to get the next rows after a specific pallet_cd.
For example if i give the parameter a
pallet_Cd = "00801004718000000007"
I just want to bring back the rows for
pallet cd = "00801004718000000007, 00801004718000000008, 00801004718000000009"
Any help with this is appreciated!

Seems pretty straightforward...
SELECT TOP 10 Line_ID, Run_Date, Product_ID, Pallet_Cd, Run_Qty
FROM YourTable
WHERE Pallet_Cd >= '00801004718000000007'
ORDER BY Pallet_Cd
This will select the next 10 records including the specified pallet code when you order by the Pallet_Cd.

If the pallet_Cd are chronological just ORDER BY Pallet_Cd and to SELECT TOP 10 WHERE Pallet_Cd >= X

Related

Keep first record in group and populate rest with Null/0 in SQL?

I have the following table in my database:
date sales
1 2010-12-13 10
2 2010-12-13 10
3 2010-12-13 10
4 2010-12-13 10
5 2010-12-13 10
6 2010-12-14 20
7 2010-12-14 20
8 2010-12-14 20
9 2010-12-14 20
10 2010-12-14 20
Is there a way to attain the first record only and populate the rest with NULL or 0 for the remainder of the group? AS the grouping will be done by date and sales:
For example the intended output is:
date sales
1 2010-12-13 10
2 2010-12-13 0
3 2010-12-13 0
4 2010-12-13 0
5 2010-12-13 0
6 2010-12-14 20
7 2010-12-14 0
8 2010-12-14 0
9 2010-12-14 0
10 2010-12-14 0
So essentially to keep the first record but make the rest of the records in the group be 0 (maybe Null if that is quicker/easier)
The closest i have got to solving this is attaining just the first record through an inner join - but I think a partition over may solve it - just stuck at the moment!
Any help appreciated!
Using SQLite - but also GCP (SQL) is accesible to me
This might work in SQLite:
CASE WHEN id = MIN(id) OVER(PARTITION BY date) THEN sales ELSE 0 END as sales
If it doesn't you can prepare a subquery that has only the min ID per date and join it in:
SELECT
CASE WHEN y.id IS NULL THEN 0 ELSE sales END as sales
FROM
x
LEFT JOIN (SELECT MIN(id) as id FROM x GROUP BY date) y ON x.id= y.id

How do i join the last record from one table where the date is older than other table?

This is my first post here, and the first problem i havent been able to find a solution to on my own. I have a MainTable that contains the fields: Date, MinutesActiveWork (And other not relevant fields). I have a second table that contains the fields: ID, id_Workarea, GoalOfActiveMinutes, GoalActiveFrom.
I want to make a query that returns all records from MainTable, and the active goal for the date.
Exampel:
Maintable (Date = dd/mm/yyyy)
ID Date ActvWrkMin WrkAreaID
1 01-01-2019 45 1
2 02-01-2019 50 1
3 03-01-2019 48 1
GoalTable:
ID id_Workarea Goal GlActvFrm
1 1 45 01-01-2019
2 2 90 01-01-2019
3 1 50 03-01-2019
What i want from my query:
IDMain Date ActvWrkMin Goal WrkAreaID
1 01-01-2019 45 45 1
2 02-01-2019 50 45 1
3 03-01-2019 48 50 1
The query that i have now is really close to what i want. But the problem is that the query outputs all goals that is less than the date from MainTable (It makes sense why, but i dont know what criteria to type to fix it). Like so:
IDMain Date ActvWrkMin Goal WrkAreaID
1 01-01-2019 45 45 1
2 02-01-2019 50 45 1
3 03-01-2019 48 45 1 <-- Dont want this one
3 03-01-2019 48 50 1
My query
SELECT tblMain.Date, tblMain.ActiveWorkMins, tblGoal.Goal
FROM VtblSumpMain AS tblMain LEFT JOIN (
SELECT VtblGoalsForWorkareas.idWorkArea, VtblGoalsForWorkareas.Goal, VtblGoalsForWorkareas.GoalActiveFrom (THIS IS THE DATE FIELD)
FROM VtblGoalsForWorkareas
WHERE VtblGoalsForWorkareas.idWorkArea= 1) AS tblGoal ON tblMain.Date > tblGoal.GoalActiveFrom
ORDER BY tblMain.Date
(I know i could do this pretty simple with Dlookup, but that is just not fast enough)
Thanks for any advice!
For this, I think you have to use the nested query as I mention below.
select tblMain.id,tblMain.Date,tblMain.ActvWrkMin, tblMain.WrkAreaID,
(select top 1 Goal
from GoalTable as gtbl
where gtbl.id_workarea = 1
and tblmain.[Date] >= gtbl.glActvFrm order by gtbl.glActvFrm desc) as Goal
from Maintable as tblMain
Check the below image for the result which is generated from this query.
I hope this will solve your issue.

Difference of values that belong to same group but stored in two rows

I have a problem where i need to fetch 2 specific records with 2 different value and find the difference between their amount. This needs to be done for each device.
Lets take the following table as example
DevID reason amount DateTime
--------------------------------------------------
99 5 84 18-12-2016 18:10
99 0 35 18-12-2016 18:11
99 0 80 18-12-2016 18:12
99 0 34 18-12-2016 18:15
23 5 36 18-12-2016 18:16
23 4 22 18-12-2016 18:17
23 1 22 18-12-2016 18:18
23 2 22 18-12-2016 18:19
99 2 11 18-12-2016 18:20
99 8 50 18-12-2016 18:21
99 0 23 18-12-2016 18:22
99 5 06 18-12-2016 18:25
99 8 12 18-12-2016 18:30
So my reason of interest is 5 and 8. 5 is device logon and 8 is logout and other numbers refer to other things.
I want to fetch records with device logon reason(5) and the next device logout(8) and find the difference in its amount value so in the table above for device 99, amount for reason 5 is 84 and the logout event(8) is 50, so the difference is 34 which if greater than 10 i need list that device.
(please note there is another case of 5 and 8 for the same record, the difference is not greater than 5) but the first set has diff greater than 10 so we need to display that device id
So the expected output for the above is
DevID
-------
99
i was thinking of join
Join table A which has all records with 5(sorted by deviceid,date) and table B which has all records of with 8 and then subtract their amounts and display the records with value greater than 10.
Not sure if join is the way to go? any simpler/fast solution?
You can use LEAD function to match logon time with logout:
WITH cte AS (
SELECT devid
, reason
, amount
, LEAD(reason) OVER (PARTITION BY devid ORDER BY datetime) AS next_reason
, LEAD(amount) OVER (PARTITION BY devid ORDER BY datetime) AS next_amount
FROM t
WHERE reason IN (5, 8)
)
SELECT *, amount - next_amount AS diff
FROM cte
WHERE reason = 5 -- logon
AND next_reason = 8 -- next event is a logout
AND amount - next_amount >= 10 -- difference of current and next
You can get the next "8" value using window functions. Then join and filter:
select t.*,
(t.value - t8.value) as diff
from (select t.*,
min(case when reason = 8 then datetime end) over (partition by devid order by datetime desc) as next_8_datetime
from t
) t left join
t t8
on t8.devid = t.devid and
t8.datetime = t.next_8_datetime and
t8.reason = 8
where t.reason = 5
order by diff desc
limit 1;

How to calculate a running total that is a distinct sum of values

Consider this dataset:
id site_id type_id value date
------- ------- ------- ------- -------------------
1 1 1 50 2017-08-09 06:49:47
2 1 2 48 2017-08-10 08:19:49
3 1 1 52 2017-08-11 06:15:00
4 1 1 45 2017-08-12 10:39:47
5 1 2 40 2017-08-14 10:33:00
6 2 1 30 2017-08-09 07:25:32
7 2 2 32 2017-08-12 04:11:05
8 3 1 80 2017-08-09 19:55:12
9 3 2 75 2017-08-13 02:54:47
10 2 1 25 2017-08-15 10:00:05
I would like to construct a query that returns a running total for each date by type. I can get close with a window function, but I only want the latest value for each site to be summed for the running total (a simple window function will not work because it sums all values up to a date--not just the last values for each site). So I guess it could be better described as a running distinct total?
The result I'm looking for would be like this:
type_id date sum
------- ------------------- -------
1 2017-08-09 06:49:47 50
1 2017-08-09 07:25:32 80
1 2017-08-09 19:55:12 160
1 2017-08-11 06:15:00 162
1 2017-08-12 10:39:47 155
1 2017-08-15 10:00:05 150
2 2017-08-10 08:19:49 48
2 2017-08-12 04:11:05 80
2 2017-08-13 02:54:47 155
2 2017-08-14 10:33:00 147
The key here is that the sum is not a running sum. It should only be the sum of the most recent values for each site, by type, at each date. I think I can help explain it by walking through the result set I've provided above. For my explanation, I'll walk through the original data chronologically and try to explain the expected result.
The first row of the result starts us off, at 2017-08-09 06:49:47, where chronologically, there is only one record of type 1 and it is 50, so that is our sum for 2017-08-09 06:49:47.
The second row of the result is at 2017-08-09 07:25:32, at this point in time we have 2 unique sites with values for type_id = 1. They have values of 50 and 30, so the sum is 80.
The third row of the result occurs at 2017-08-09 19:55:12, where now we have 3 sites with values for type_id = 1. 50 + 30 + 80 = 160.
The fourth row is where it gets interesting. At 2017-08-11 06:15:00 there are 4 records with a type_id = 1, but 2 of them are for the same site. I'm only interested in the most recent value for each site so the values I'd like to sum are: 30 + 80 + 52 resulting in 162.
The 5th row is similar to the 4th since the value for site_id:1, type_id:1 has changed again and is now 45. This results in the latest values for type_id:1 at 2017-08-12 10:39:47 are now: 30 + 80 + 45 = 155.
Reviewing the 6th row is also interesting when we consider that at 2017-08-15 10:00:05, site 2 has a new value for type_id 1, which gives us: 80 + 45 + 25 = 150 for 2017-08-15 10:00:05.
You can get a cumulative total (running total) by including an ORDER BY clause in your window frame.
select
type_id,
date,
sum(value) over (partition by type_id order by date) as sum
from your_table;
The ORDER BY works because
The default framing option is RANGE UNBOUNDED PRECEDING, which is the same as RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
SELECT type_id,
date,
SUM(value) OVER (PARTITION BY type_id ORDER BY type_id, date) - (SUM(value) OVER (PARTITION BY type_id, site_id ORDER BY type_id, date) - value) AS sum
FROM your_table
ORDER BY type_id,
date

Running total of rows by ID

I have a list of IDs, transactions, and the date of those transactions. I want to create a count of each transaction within each ID.
The starting table I have is looks something like this:
id trxn_dt trxn_amt
1 10/31/2014 58
1 11/9/2014 34
1 12/10/2014 12
2 7/8/2014 78
2 11/20/2014 99
3 1/5/2014 120
4 2/17/2014 588
4 2/18/2014 8
4 3/9/2014 65
4 4/25/2014 74
and I want the end result to look something like this:
id trxn_dt trxn_amt trxn_count
1 10/31/2014 58 1
1 11/9/2014 34 2
1 12/10/2014 12 3
2 7/8/2014 78 1
2 11/20/2014 99 2
3 1/5/2014 120 1
4 2/17/2014 588 1
4 2/18/2014 8 2
4 3/9/2014 65 3
4 4/25/2014 74 4
Count(distinct(id)) would only give me the overall number of distinct IDs and not a running total by each ID that restarts at each new ID.
Thank you!
In SQL-Server you can use ROW_NUMBER in following:
SELECT id,
trxn_dt,
trxn_amt,
ROW_NUMBER() OVER(PARTITION BY Id ORDER BY Id, trxn_dt) AS trxn_count
FROM StarningTable
In MySQL you can do in following:
SELECT
t.id,
t.trxn_dt,
t.trxn_amt,
#cur:= IF(id=#id, #cur+1, 1) AS RowNumber,
#id := id
FROM
StarningTable t
CROSS JOIN
(SELECT #id:=(SELECT MIN(id) FROM StarningTable t), #cur:=0) AS init
ORDER BY
t.id
using Row_number we can achieve this
Select *,
ROW_NUMBER()OVER(PARTITION BY id ORDER BY (SELECT NULL))trxn_count
from Transactions