SQL - Sqlite Query: obtain the fields where one number is greater than another, if less than 3 complete with the first, always 3 - sql

Well i made a query that is not working
i have a table like this
_id - E1
-----------
1 - 100
2 - 335
3 - 420
4 - 440
5 - 500
6 - 514
7 - 524
8 - 534
9 - 544
10 - 552
11 - 559
12 - 607
13 - 615
14 - 623
15 - 631
16 - 639
and the query that i made:
SELECT * FROM
(SELECT * FROM Table WHERE E1 > 633 AND _sentido = 'V'
UNION
SELECT * FROM Table) LIMIT 3
when i execute this i get
_id - E1
-----------
1 - 100
2 - 335
3 - 420
but what i really want is
_id - E1
-----------
1 - 639
2 - 100
3 - 335
if the last row and there are NOT 3 selected rows then complete with the first to reach 3
Always 3 rows!
I hope you can help me, John

You have a clever approach, but it is not going to work. The ordering of subqueries is not guaranteed. What you want is to order by your condition first and then fill out with the rest. Try this:
SELECT *
FROM table
ORDER BY (case when E1 > 633 AND _sentido = 'V' then 1 else 2 end)
LIMIT 3;
This puts the records you are interested in first. The limit 3 will retrieve those records (up to 3) and then pad remaining rows with the rest of the records.

Related

Convert This SQL Query to ANSI SQL

I would like to convert this SQL query into ANSI SQL. I am having trouble wrapping my head around the logic of this query.
I use Snowflake Data Warehouse, but it does not understand this query because of the 'delete' statement right before join, so I am trying to break it down. From my understanding the row number column is giving me the order from 1 to N based on timestamp and placing it in C. Then C is joined against itself on the rows other than the first row (based on id) and placed in C1. Then C1 is deleted from the overall data, which leaves only the first row.
I may be understanding the logic incorrectly, but I am not used to seeing the 'delete' statement right before a join. Let me know if I got the logic right, or point me in the right direction.
This query was copy/pasted from THIS stackoverflow question which has the exact situation I am trying to solve, but on a much larger scale.
with C as
(
select ID,
row_number() over(order by DT) as rn
from YourTable
)
delete C1
from C as C1
inner join C as C2
on C1.rn = C2.rn-1 and
C1.ID = C2.ID
The specific problem I am trying to solve is this. Let's assume I have this table. I need to partition the rows by primary key combinations (primKey 1 & 2) while maintaining timestamp order.
ID primKey1 primKey2 checkVar1 checkVar2 theTimestamp
100 1 2 302 423 2001-07-13
101 3 6 506 236 2005-10-25
100 1 2 302 423 2002-08-15
101 3 6 506 236 2008-12-05
101 3 6 300 100 2010-06-10
100 1 2 407 309 2005-09-05
100 1 2 302 423 2012-05-09
100 1 2 302 423 2003-07-24
Once the rows are partitioned and the timestamp is ordered within each partition, I need to delete the duplicate checkVar combination (checkVar 1 & 2) rows until the next change. Thus leaving me with the earliest unique row. The rows with asterisks are the ones which need to be removed since they are duplicates.
ID primKey1 primKey2 checkVar1 checkVar2 theTimestamp
100 1 2 302 423 2001-07-13
*100 1 2 302 423 2002-08-15
*100 1 2 302 423 2003-07-24
100 1 2 407 309 2005-09-05
100 1 2 302 423 2012-05-09
101 3 6 506 236 2005-10-25
*101 3 6 506 236 2008-12-05
101 3 6 300 100 2010-06-10
This is the final result. As you can see for ID=100, even though the 1st and 3rd record are the same, the checkVar combination changed in between, which is fine. I am only removing the duplicates until the values change.
ID primKey1 primKey2 checkVar1 checkVar2 theTimestamp
100 1 2 302 423 2001-07-13
100 1 2 407 309 2005-09-05
100 1 2 302 423 2012-05-09
101 3 6 506 236 2005-10-25
101 3 6 300 100 2010-06-10
If you want to keep the earliest row for each id, then you can use:
delete from yourtable yt
where yt.dt > (select min(yt2.dt)
from yourtable yt
where yt2.id = yd.id
);
Your query would not do this, if that is your intent.

Properly 'Joining' two Cross Applies

I've got a query with three Cross-Applies that gather data from three different tables. The first Cr-Ap assists the 2nd and 3rd Cr-Ap's. It finds the most recent ID of a certain refill for a 'cartridge', the higher the ID the more recent the refill.
The second and third Cr-Ap's gather the SUMS of items that have been refilled and items that have been dispensed under the most recent Refill.
If I run the query for Cr-Ap 2 or 3 separately the output would look something like:
ID Amount
1 100
2 1000
3 100
4 0
5 0
etc
Amount would be either the amount of dispensed or refilled items.
Only I don't want to run these queries separately, I want them next to each other.
So what I want is a table that looks like this:
ID Refill Dispense
1 100 1
2 1000 5
3 100 7
4 0 99
5 0 3
etc
My gut tells me to do
INNER JOIN crossaply2 ON crossapply3.ID = crossapply2.ID
But this doesn't work. I'm still new to SQL so I don't exactly know what I can and can't join, what I do know is that you can use crossapply as a join (sorta?). I think that might be what I need to do here, I just don't know how.
But that's not it, there's another complication, there are certain refills where nothing gets dispensed. In these scenarios the crossapply I wrote for dispenses won't return anything for that refillID. With nothing I don't mean NULL, I mean it just skips the refillID. But I'd like to see a 0 in those cases. Because it just skips over those ID's I can't get COALESCE or ISNULL to work, this might also complicate the joining of these two applies. Because an INNER JOIN would skip any line where there is no Dispensed amount, even though there is a Refilled amount Id like to see.
Here is my code:
-- Dispensed SUM and Refilled SUM combined
SELECT [CartridgeRefill].[FK_CartridgeRegistration_Id]
,Refills.Refilled
,Dispenses.Dispensed
FROM [CartridgeRefill]
CROSS APPLY(
SELECT MAX([CartridgeRefill].[Id]) AS RecentRefillID
FROM [CartridgeRefill]
GROUP BY [CartridgeRefill].[FK_CartridgeRegistration_Id]
) AS RecentRefill
CROSS APPLY(
SELECT [CartridgeRefill].[FK_CartridgeRegistration_Id] AS RefilledID
,SUM([CartridgeRefillMedication].[Amount]) AS Refilled
FROM [CartridgeRefillMedication]
INNER JOIN [CartridgeRefill] ON [CartridgeRefillMedication].[FK_CartridgeRefill_Id] = [CartridgeRefill].[Id]
WHERE [CartridgeRefillMedication].[FK_CartridgeRefill_Id] = RecentRefill.RecentRefillID
GROUP BY [CartridgeRefill].[FK_CartridgeRegistration_Id]
) AS Refills
CROSS APPLY(
SELECT [CartridgeRefill].[FK_CartridgeRegistration_Id] AS DispensedID
,SUM([CartridgeDispenseAttempt].[Amount]) AS Dispensed
FROM [CartridgeDispenseAttempt]
INNER JOIN [CartridgeRefill] ON [CartridgeDispenseAttempt].[FK_CartridgeRefill_Id] = [CartridgeRefill].[Id]
WHERE [CartridgeDispenseAttempt].[FK_CartridgeRefill_Id] = RecentRefill.RecentRefillID
GROUP BY [CartridgeRefill].[FK_CartridgeRegistration_Id]
) AS Dispenses
GO
The output of this code is as follows:
1 300 1
1 300 1
1 200 194
1 200 194
1 200 8
1 200 8
1 0 39
1 0 39
1 100 14
1 100 14
1 200 1
1 200 1
1 0 28
1 0 28
1 1000 102
1 1000 102
1 1000 557
1 1000 557
1 2000 92
1 2000 92
1 100 75
1 100 75
1 100 100
1 100 100
1 100 51
1 100 51
1 600 28
1 600 28
1 200 47
1 200 47
1 200 152
1 200 152
1 234 26
1 234 26
1 0 227
1 0 227
1 10 6
1 10 6
1 300 86
1 300 86
1 0 194
1 0 194
1 500 18
1 500 18
1 1000 51
1 1000 51
1 1000 56
1 1000 56
1 500 48
1 500 48
1 0 10
1 0 10
1 1500 111
1 1500 111
1 56 79
1 56 79
1 100 6
1 100 6
1 44 134
1 44 134
1 1000 488
1 1000 488
1 100 32
1 100 32
1 100 178
1 100 178
1 500 672
1 500 672
1 200 26
1 200 26
1 500 373
1 500 373
1 100 10
1 100 10
1 900 28
1 900 28
2 900 28
2 900 28
2 900 28
etc
It is total nonsense that I can't do much with, it goes on for about 20k lines and goes through all the ID's, eventually.
Any help is more than appreciated :)
Looks like overcomplicated a bit.
Try
WITH cr AS (
SELECT [FK_CartridgeRegistration_Id]
,MAX([CartridgeRefill].[Id]) RecentRefillID
FROM [CartridgeRefill]
GROUP BY [FK_CartridgeRegistration_Id]
)
SELECT cr.[FK_CartridgeRegistration_Id], Refills.Refilled, Dispenses.Dispensed
FROM cr
CROSS APPLY(
SELECT SUM(crm.[Amount]) AS Refilled
FROM [CartridgeRefillMedication] crm
WHERE crm.[FK_CartridgeRefill_Id] = cr.RecentRefillID
) AS Refills
CROSS APPLY(
SELECT SUM(cda.[Amount]) AS Dispensed
FROM [CartridgeDispenseAttempt] cda
WHERE cda.[FK_CartridgeRefill_Id] = cr.RecentRefillID
) AS Dispenses;

Update values based on sequence of rows - Oracle SQL

I have a table:
table1
u_a_id d_c_s c_nm c_v c_se line_num
19 878 Test Code - Individual CO 1 30
19 878 Test Code - Individual PR 1 31
19 878 Test Code - Individual PR 2 32
19 878 Test Code - Individual CO 2 33
19 878 Test Code - Individual CO 1 33
19 878 Test Code - Individual PR 1 34
19 878 Test Code - Individual PR 2 35
19 878 Test Code - Individual CO 2 36
19 878 Test Code - Individual PR 3 37
19 878 Test Code - Individual CO 3 38
For each u_a_id, order by line_num, I need to identify if combination of c_nm and c_se is repeated. If the combination is repeated, then I need to update the following based on the sequence:
d_c_s to 12000 for First
d_c_s to 12001 for Second
d_c_s to 12002 for Third
Append First to c_nm
Append Second to c_nm
Append Third to c_nm
The output would look like:
u_a_id d_c_s c_nm c_v c_se line_num
19 12000 Test Code, First - Individual CO 1 30
19 12001 Test Code, Second - Individual PR 1 31
19 12000 Test Code, First - Individual PR 2 32
19 12001 Test Code, Second - Individual CO 2 33
19 12000 Test Code, First - Individual CO 1 33
19 12001 Test Code, Second - Individual PR 1 34
19 12000 Test Code, First - Individual PR 2 35
19 12001 Test Code, Second - Individual CO 2 36
19 12000 Test Code, First - Individual PR 3 37
19 12001 Test Code, Second - Individual CO 3 38
Is there anyway in SQL to do it?
What you describe is more like this:
select . . .,
(12000 - 1 + seqnum) as d_c_s,
replace(c_nm, ' - ',
(case seqnum
when 1 then ', First - '
when 2 then ', Second - '
when 3 then ', Third - '
else ' - '
end)
) as c_nm
from (select t.*,
row_number() over (partition by c_nm, c_se order by line_num) as seqnum,
count(*) over (partition by c_nm, c_se) as cnt
from t
) t

Calculate Sub Query Column Based On Calculated Column

I have a table ScheduleRotationDetail that contains these as columns:
ScheduleRotationID ScheduleID Ordinal Duration
379 61 1 1
379 379 2 20
379 512 3 1
379 89 4 20
I have a query that goes like this in order to get the day of the year each schedule is supposed to start on:
SELECT ScheduleID, Ordinal, Duration,
,Duration * 7 AS DurationDays
,( SELECT ( ISNULL( SUM(ISNULL( Duration, 0 )), 0 ) - 1 ) * 7
FROM ScheduleRotationDetail WHERE ScheduleRotationID = srd.ScheduleRotationID
AND Ordinal <= srd.Ordinal ) AS StartDay
FROM ScheduleRotationDetail srd
WHERE srd.ScheduleRotationID = 379
That outputs this as the result set:
ScheduleID Ordinal Duration DurationDays StartDay
61 1 1 7 0
379 2 20 140 140
512 3 1 7 147
89 4 20 140 287
Yet what I need the start day column values to be are:
0
7
147
154
I have tried CTEs but can't get it to work so I've come to here for advice.
It looks like you want a cumulative sum. In SQL Server 2012+, you can do:
SELECT ScheduleID, Ordinal, Duration,
SUM(Duration*7) OVER (ORDER BY Ordinal) - Duration*7 as StartDate
FROM ScheduleRotationDetail srd ;
In earlier versions, you can use APPLY for this purpose (or a correlated subquery).

Select from table repeat first value for combination of two keys

I would like to transfer some existing data into new data table.
I have table with substitutions:
- ID
- currentItemId
- formerItemId
- contentId
For the same content there is possibility I have multiple entries for combinations currentItemId and formerItemId.
Let me show how it is now:
ID_T1 currentItemId formerItemId contentId
1 100 200 300
2 100 200 301
3 100 200 302
4 105 201 303
5 105 201 304
6 110 205 320
7 111 206 321
8 120 204 322
9 130 208 323
10 130 208 324
Now, I would like to select TOP ID for each combination formerItemId and currentItemId:
ID ID_T1 contentId
1 1 300
2 1 301
3 1 302
4 4 303
5 4 304
6 6 320
7 7 321
8 8 322
9 9 323
10 9 324
Both tables also contains timestamp and some other data - I haven't included that in order example to be more understandable.
I tried self join (no success), nested select (gives me right value for the original combination, but it doesn't repeat, it gives me NULL on ID for other records), but nothing seems to work. Tried something like:
SELECT di1.ID,
(SELECT TOP(1) di1.ID
FROM TABLE
WHERE
di1.currentItemtId = di2.currentItemtId AND di1.formerItemId = di1.formerItemId
) AS repeat
,di2.deleteItemId
,di1.currentitemtId
,di1.formerItemId
,di1.contentId
FROM Table di1
LEFT JOIN
Table di2 ON di1.ID = di2.ID
But this way ID doesn't repeat - I get same values for ID as in ordinary select.
I am using SQL server 2008.
Any help would be greatly appreciated.
Please try:
SELECT
MIN(ID) OVER (PARTITION BY currentItemId, formerItemId) ID,
currentItemId,
formerItemId,
contentId
FROM YourTable
SELECT
ID,
MIN(ID) OVER (PARTITION BY currentItemId, formerItemId) ID_T1,
contentId
FROM YourTable