How to create or combine three CTE - sql-server

I hope you can help/guide me, I have one working CTE and I would like to add two more SQL queries to have one SQL statement and I am encountering various type of error as I try to play around with the parameters...
I have less experience in CTE so please bear with me...my purpose is to create an SSRS report using report builder and I want to combine the output of each query into a column bar...
Here is the working CTE which is my first Column Bar in my SSRS report...
WITH Cnt AS (
select Count(Distinct UserID) as Entitled_Users, DATEFROMPARTS(YEAR(t.WhenAddedToGroup),MONTH(t.WhenAddedToGroup),1) as When_Added_To_Group
from Membership t
where FirstName not like '%test%' and LastName not like '%test%' and FirstName not like '%user%' and LastName not like '%user%' and Account_Disabled not like 'YES' and Obj_Type not like 'NON_USER' and Region not like 'EMEA' and Region not like 'CCLA' and SecGroup IN ('SecurityGroup1', 'SecurityGroup2', 'SecurityGroup3', 'SecurityGroup4')and curr_member like 'yes' and ATTUID is not null and WhenAddedToGroup is not null
Group By DATEFROMPARTS(YEAR(t.WhenAddedToGroup),MONTH(t.WhenAddedToGroup),1)
)
Select When_Added_To_Group, Entitled_Users, (Select SUM(t2.Entitled_Users) as Entitled_Users
from Cnt T2
where T2.When_Added_To_Group <=T1.When_Added_To_Group) as Running_Total
from Cnt T1
Below is the second SQL query that I am hoping I can merge or join with the above CTE which will be the second column bar of my Column Report in SSRS..
SELECT c.EventType, DATEFROMPARTS(YEAR(c.Event_Date),MONTH(c.Event_Date),1) as Concurrent_Date, MAX(c.MAX_Concurrent_Users) as Peak_Concurrent_Users, c.Hub
FROM vNon_Concurrent_Users c
where c.EventType like 'Broker_Daily_Max_Users' and c.Hub like 'TOK Hub'
group by DATEFROMPARTS(YEAR(c.Event_Date),MONTH(c.Event_Date),1), c.Hub, c.EventType
below is my third SQL Query which will be the third column bar of my SSRS report...
select hs.hub, hs.NAME, DATEFROMPARTS(YEAR(hs.BOOT_TIME),MONTH(hs.BOOT_TIME),1) as Host_Boot_Time,
ROUND(CAST(hs.CPU_CORE_COUNT as FLOAT)*hs.CPU_Hz*count(cast(hs.HOSTID as BIGINT))/800000000,0) as Host_Capacity
from HVD_VPXV_HOSTS as hs WITH (NOLOCK,NOWAIT)
where hs.hub like 'TOK Hub'
group by hs.hub, hs.CPU_CORE_COUNT, hs.CPU_Hz, hs.NAME, hs.BOOT_TIME
order by hs.BOOT_TIME desc
the where clause of the three queries are:
When_Added_To_Group=Concurrent_date,
When_Added_To_Group=Host_Boot_time
as mentioned above I tried playing around with the paramters but I get different errors...below is one (of many) statement which I tried that I can give as an example:
WITH Cnt AS (
select Count(Distinct UserID) as Entitled_Users, DATEFROMPARTS(YEAR(t.WhenAddedToGroup),MONTH(t.WhenAddedToGroup),1) as When_Added_To_Group
from HVDMembership t
where FirstName not like '%test%' and LastName not like '%test%' and FirstName not like '%user%' and LastName not like '%user%' and Account_Disabled not like 'YES' and Obj_Type not like 'NON_USER' and Region not like 'EMEA' and Region not like 'CCLA' and SecGroup IN ('SecurityGroup1', 'SecurityGroup2', 'SecurityGroup3', 'SecurityGroup4')and curr_member like 'yes' and ATTUID is not null and WhenAddedToGroup is not null
Group By DATEFROMPARTS(YEAR(t.WhenAddedToGroup),MONTH(t.WhenAddedToGroup),1)
)
, Concurrent
as (
SELECT c.EventType, DATEFROMPARTS(YEAR(c.Event_Date),MONTH(c.Event_Date),1) as Concurrent_Date, MAX(c.MAX_Concurrent_Users) as Peak_Concurrent_Users, c.Hub
FROM vNon_Concurrent_Users c
where c.EventType like 'Broker_Daily_Max_Users' and c.Hub like 'TOK Hub'
group by DATEFROMPARTS(YEAR(c.Event_Date),MONTH(c.Event_Date),1), c.Hub, c.EventType
)
, Capacity
as (
select hs.hub, hs.NAME, DATEFROMPARTS(YEAR(hs.BOOT_TIME),MONTH(hs.BOOT_TIME),1) as Host_Boot_Time,
ROUND(CAST(hs.CPU_CORE_COUNT as FLOAT)*hs.CPU_Hz*count(cast(hs.HOSTID as BIGINT))/800000000,0) as Host_Capacity
from HVD_VPXV_HOSTS as hs WITH (NOLOCK,NOWAIT)
where hs.hub like 'TOK Hub'
group by hs.hub, hs.CPU_CORE_COUNT, hs.CPU_Hz, hs.NAME, hs.BOOT_TIME
)
Select When_Added_To_Group, Entitled_Users, (Select SUM(t2.Entitled_Users) as Entitled_Users
from Cnt T2
where T2.When_Added_To_Group <=T1.When_Added_To_Group) as Running_Total,
Select Peak_concurrent_users, concurrent_date from Concurrent,
select SUM(Host_Capacity), Host_Boot_Time from Capacity
where When_Added_To_Group=Concurrent_date, When_Added_To_Group=Host_Boot_time
from Cnt T1
Thanks in advance.

CTEs must be referenced only in the first SQL statement after the CTE. You have multiple selects. That is your first problem.
The second problem is that your CTEs don't appear to have data that is related to each other. Without knowing what you would expect as the results from sample data, it is pretty much impossible to advise you on how you should do the query. I can't make any meaning out of what you are trying to do, so I don't know what query you want to write. I could randomly suggest 3-4 different alternative queries but that would likely be less useful to you than asking you to provide information on what you are trying for and what your business rules should be and sample data. You simply cannot effectively write queries without understanding the underlying meaning of the data.

Related

Splitting Data from a Column into two Columns

I have data in a column called "Medication_Description". First I need to
then find out who that received Tylenol also received a second drug (Ibuprofen here).
I also only want the top two results for each MRN (i.e. patient). I only want data for the past year.
Later I will be plugging this into an SSRS report where I will determine the percentage of patients that received both drugs.
I've played with a couple different ways of getting this to work but can't get it working quite right.
The data in this table looks like this:
As for desired results, I'd like to have something like this:
Blockquote
For MRN 654321, no Ibuprofen was administered so it returns NULL (it could also return another drug name - doesn't matter too much. I just need to be able to count the results later to determine a percentage).
For MRN 246824, only one dose of Ibuprofen was administered so the second line is NULL.
Below is my latest attempt but (as you can see) Med1 and Med2 will always reflect the same exact data - how can I make Med1 reflect one medication and Med2 reflect a second?
SELECT [MRN], [Med1], [Med2], [Row_Num], [Department_Name], [Date]
FROM
( SELECT [MRN], [Medication_Description] AS [Med1], [Medication_Description] AS [Med2],
ROW_NUMBER() OVER (PARTITION BY [MRN]
ORDER BY [Medication_Description] DESC
)
AS [Row_Num],
[Date],
[Department_Name]
FROM T_Med_Orders
WHERE [DATE] BETWEEN dateadd(year,-1,getdate()) AND getdate()
AND [Department_Name] LIKE 'ICU'
--First Med Must Match "Tylenol" but 2nd should match any result...???
AND Medication_Description LIKE '%Tylenol%'
)
tmp
WHERE
[Row_Num] <= 2
AND Med1 LIKE '%Tylenol%'
--AND Med2 LIKE '%Ibuprofen%'
AND [DATE] BETWEEN dateadd(year,-1,getdate()) AND getdate()
ORDER BY [MRN]
You have a solid start, but I think you're being too ambitious with your query. While there are ways to optimize the query, using Partitions may be overkill for the current requirements. What I ended up doing was to make two CTEs where each is filtered to the individual medicine being identified. I can LEFT JOIN those to the source table and filter it to only show results where the CTE values are NOT NULL. I can also apply the other DeptName and Date clauses, although I have not done so in my code snippet.
The main drawback is that this format would require more and more CTEs if you wanted to expand to include other medicines, swiftly reducing optimization further. But without knowing how MedicationDescription is formatted (or if it even has a standard format) I can't write that for you.
WITH Tylenol_CTE AS
(SELECT *, 'Tylenol' AS [FilteredMedicine]
FROM #Temp
WHERE Medication_Description LIKE '%Tylenol%')
,Ibuprofen_CTE AS
(SELECT *, 'Ibuprofen' AS [FilteredMedicine]
FROM #Temp
WHERE Medication_Description LIKE '%Ibuprofen%')
SELECT t.*
, Tylenol_CTE.[FilteredMedicine] AS Med1
, Ibuprofen_CTE.[FilteredMedicine] AS Med2
FROM #Temp t
LEFT JOIN Tylenol_CTE
ON t.MRN = Tylenol_CTE.MRN
AND t.Date = Tylenol_CTE.Date
LEFT JOIN Ibuprofen_CTE
ON t.MRN = Ibuprofen_CTE.MRN
AND t.Date = Ibuprofen_CTE.Date
WHERE Ibuprofen_CTE.Medication_Description IS NOT NULL
AND Tylenol_CTE.Medication_Description IS NOT NULL

how to select first rows distinct by a column name in a sub-query in sql-server?

Actually I am building a Skype like tool wherein I have to show last 10 distinct users who have logged in my web application.
I have maintained a table in sql-server where there is one field called last_active_time. So, my requirement is to sort the table by last_active_time and show all the columns of last 10 distinct users.
There is another field called WWID which uniquely identifies a user.
I am able to find the distinct WWID but not able to select the all the columns of those rows.
I am using below query for finding the distinct wwid :
select distinct(wwid) from(select top 100 * from dbo.rvpvisitors where last_active_time!='' order by last_active_time DESC) as newView;
But how do I find those distinct rows. I want to show how much time they are away fromm web apps using the diff between curr time and last active time.
I am new to sql, may be the question is naive, but struggling to get it right.
If you are using proper data types for your columns you won't need a subquery to get that result, the following query should do the trick
SELECT TOP 10
[wwid]
,MAX([last_active_time]) AS [last_active_time]
FROM [dbo].[rvpvisitors]
WHERE
[last_active_time] != ''
GROUP BY
[wwid]
ORDER BY
[last_active_time] DESC
If the column [last_active_time] is of type varchar/nvarchar (which probably is the case since you check for empty strings in the WHERE statement) you might need to use CAST or CONVERT to treat it as an actual date, and be able to use function like MIN/MAX on it.
In general I would suggest you to use proper data types for your column, if you have dates or timestamps data use the "date" or "datetime2" data types
Edit:
The query aggregates the data based on the column [wwid], and for each returns the maximum [last_active_time].
The result is then sorted and filtered.
In order to add more columns "as-is" (without aggregating them) just add them in the SELECT and GROUP BY sections.
If you need more aggregated columns add them in the SELECT with the appropriate aggregation function (MIN/MAX/SUM/etc)
I suggest you have a look at GROUP BY on W3
To know more about the "execution order" of the instruction you can have a look here
You can solve problem like this by rank ordering the results by a key and finding the last x of those items, this removes duplicates while preserving the key order.
;
WITH RankOrdered AS
(
SELECT
*,
wwidRank = ROW_NUMBER() OVER (PARTITION BY wwid ORDER BY last_active_time DESC )
FROM
dbo.rvpvisitors
where
last_active_time!=''
)
SELECT TOP(10) * FROM RankOrdered WHERE wwidRank = 1
If my understanding is right, below query will give the desired output.
You can have conditions according to your need.
select top 10 distinct wwid from dbo.rvpvisitors order by last_active_time desc

Subtract one column from another and get running total SQL Server 2008 R2

I hate to ask a question that it seems like the answer already exists somewhere, but I've been working through various articles over the last couple days (https://www.sqlshack.com/running-running-totals-sql-server/ , Calculate a Running Total in SQL Server, https://learn.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-2017 etc.) with minimal progress.
It seems most of the examples given provide a way to join (a self join) or some other WHERE clause to narrow the result set? Anyway, I have a table Location that has columns for PassengersOn and PassengersOff; I would like to be able to calculate the running total of passengers on board at a given time so that my resulting table might look something like this
Which shows a running total (OnBoard) for passengers after each location.
Also, I am aware of the OVER clause available in SQL Server 2012, but unfortunately I'm using 2008 R2.
Again sorry for what may be a duplicate question, but I don't see how I can limit my result set based on a join or WHERE clause since I don't have an incrementing column in my "location" table, instead it uses a guid.
EDIT: here is a sample of the table information
CREATE TABLE Query_8v2 (
[IDStopEvent] NVARCHAR(36),
[LocationID] NVARCHAR(6),
[LocName] NVARCHAR(5),
[PassOn] INT,
[PassOff] INT
);
INSERT INTO Query_8v2 VALUES
(N'f00e6b5b-eb64-4e6b-8b87-0000a539ee36',N'guid1',N'Loc01',0,0),
(N'617cbcae-b467-4adb-b994-00015bca9bb5',N'guid1',N'Loc01',0,59),
(N'215f92bc-8114-4dd0-a1e1-00016e4f0546',N'guid1',N'Loc01',0,42),
(N'e8eaaed5-dc0c-48a9-b39b-0001fc44576e',N'guid1',N'Loc01',0,0),
(N'4c54eef6-11f3-4114-ad9d-0004b1b3849d',N'guid1',N'Loc01',0,0),
(N'a29eb925-8226-4d89-8760-00063d64067a',N'guid1',N'Loc01',69,0),
(N'b16e1b1f-d481-447e-9771-000890fe6999',N'guid1',N'Loc01',0,69),
(N'4f5894ee-a246-4c9d-bc28-0008bc1b3614',N'guid1',N'Loc01',0,44),
(N'52e447cf-f900-4e49-94ca-0008c262a173',N'guid1',N'Loc01',0,0),
(N'f120f646-17f2-4bbb-879d-00091665ec7e',N'guid1',N'Loc01',0,0),
(N'3bbe56e0-c54c-4f3c-9f29-000c914cd724',N'guid1',N'Loc01',32,0),
(N'1ddda821-23f5-43a5-a86c-000d46d4cdc9',N'guid1',N'Loc01',0,0),
(N'b58dac6b-6cac-4bf3-af47-000e67b67582',N'guid1',N'Loc01',0,0),
(N'c9d52156-cc88-4c3c-9409-00103ba9afaa',N'guid1',N'Loc01',0,0),
(N'662d3006-938d-4a66-8999-00104632991b',N'guid1',N'Loc01',0,106),
(N'598d135b-3bdb-4d4b-9464-0010ab22b9eb',N'guid1',N'Loc01',0,0),
(N'c60e2801-efb8-41c3-9dad-00110aae0f2d',N'guid1',N'Loc01',0,0),
(N'72384001-56a3-413c-a847-0011125a5e31',N'guid1',N'Loc01',0,0),
(N'081a9c68-514a-4622-ab0d-00117909d029',N'guid1',N'Loc01',0,0),
(N'afac2c83-ee2e-4b79-8d0b-0011adc313e0',N'guid1',N'Loc01',0,0),
(N'a0f65fe9-79d2-470e-9885-000acccbf82f',N'guid2',N'Loc02',0,0),
(N'bd4371c6-896a-4a4c-9168-000b6e3d2bdd',N'guid2',N'Loc02',0,34),
(N'7c747187-905d-48f5-b9fd-000e233e2986',N'guid2',N'Loc02',21,0),
(N'a3e2773a-2310-4185-9b0c-00013204c0d4',N'guid3',N'Loc03',0,206),
(N'1a8e4c21-0550-411f-91ae-00018234e33d',N'guid3',N'Loc03',323,0),
(N'66ac5d5c-ef97-4041-92cb-0009412a4cec',N'guid3',N'Loc03',0,249),
(N'5b6b2d10-70e4-4953-bf4b-00099ffbc1cd',N'guid3',N'Loc03',183,0),
(N'0107bfcb-9628-42f3-8a4d-000bd42d8cff',N'guid3',N'Loc03',0,400),
(N'f4179bce-399a-417f-bcb1-000fce5ff5b1',N'guid3',N'Loc03',319,0),
(N'f3668d7f-4338-4c15-bb65-0000f5f6af85',N'guid4',N'Loc04',25,32),
(N'dad5af74-a873-46ff-8b61-0002a122850a',N'guid4',N'Loc04',19,75),
(N'e20b705a-6416-4876-aa96-0005e8e25d94',N'guid4',N'Loc04',48,40),
(N'2e3f93d1-65fa-4b13-a8db-0007e6e47b4a',N'guid4',N'Loc04',48,37),
(N'7bc78967-ef77-4fb7-a74d-0008dd88268a',N'guid4',N'Loc04',51,42),
(N'f409014f-189e-4e24-943b-00095acd2e38',N'guid4',N'Loc04',48,71),
(N'e9a6a04d-32da-45e6-a93b-000ae35cd97b',N'guid4',N'Loc04',63,13),
(N'5d719c25-8a20-4cce-85a2-000f6be996ba',N'guid4',N'Loc04',57,69),
(N'5d5a3666-a996-4220-b943-00110f627aee',N'guid4',N'Loc04',27,63),
(N'941880b8-0873-40ee-936b-0001b711fbba',N'guid5',N'Loc05',55,182),
(N'f3f360a1-3767-443e-ac19-000878a505eb',N'guid5',N'Loc05',62,41),
(N'd03d154b-ade6-4c06-af11-000b9fbcb218',N'guid5',N'Loc05',109,86),
(N'7c296996-32a5-46c5-bafd-000e49bf18ba',N'guid5',N'Loc05',126,68),
(N'72424ac3-7b47-44f2-9ffa-0003521bf7c2',N'guid6',N'Loc06',3,3),
(N'abb66bf1-9dab-4f56-a14c-00049b102c9c',N'guid6',N'Loc06',18,38),
(N'2db22514-3a92-4781-9232-000a6d701063',N'guid6',N'Loc06',88,34),
(N'c83239ba-4467-4d8d-9bb6-000b0c802255',N'guid6',N'Loc06',13,13),
(N'32649da2-bd02-44c3-af3a-000d33087fbe',N'guid6',N'Loc06',7,18),
(N'db9f9f3b-f4f0-4300-85c4-000f09011b60',N'guid6',N'Loc06',3,39),
(N'e6aa3c22-489d-4f97-b718-0002071629f1',N'guid7',N'Loc07',55,23),
(N'e648fff9-50ed-42a3-82e4-00027f22287f',N'guid7',N'Loc07',4,28),
(N'7b157c82-1819-4990-8147-0007f4dcaed6',N'guid7',N'Loc07',8,62),
(N'3ffecbf1-bd09-4ef8-b17f-00092211960b',N'guid7',N'Loc07',55,29),
(N'16eab156-126d-440d-a01b-0009a506e922',N'guid7',N'Loc07',3,23),
(N'69af7b49-ce4e-446c-9947-000a42bffa23',N'guid7',N'Loc07',7,8),
(N'd0ba9ab8-80dc-47c9-9f61-000e15b8c049',N'guid7',N'Loc07',3,69),
(N'77749016-19be-4657-b2d5-0005f60f5b5f',N'guid8',N'Loc08',0,163),
(N'7908e6ae-71be-4f3e-aa77-00078b16dbac',N'guid8',N'Loc08',201,0),
(N'10f13d13-9a5c-4ef8-960e-00084b5fa97c',N'guid8',N'Loc08',99,1),
(N'859c00b3-c907-4d90-92de-000e2b7f95d8',N'guid8',N'Loc08',2,167),
(N'e00136e2-e71e-4aed-afbf-00005f66f1b6',N'guid9',N'Loc09',0,299),
(N'ab711e41-e6e3-45b3-ad18-000597d39430',N'guid9',N'Loc09',0,158),
(N'301fada9-f0c1-4afb-aaf2-0005a7d0b3e8',N'guid9',N'Loc09',137,0),
(N'67d1a3f1-547d-495e-98c1-00080e3309b6',N'guid9',N'Loc09',67,0),
(N'a71a4103-dffc-40da-92b8-000a987987a2',N'guid9',N'Loc09',124,0),
(N'a60f9e16-e262-404e-9947-0000732dded4',N'guid10',N'Loc10',0,103),
(N'e4aab4d3-9c58-49fb-a9d7-0001350c9e74',N'guid10',N'Loc10',0,0),
(N'5e8617c7-d2c8-4fb4-b745-0001f8eac18a',N'guid10',N'Loc10',96,0),
(N'1864b5e5-fdda-4f9b-9522-0002e2afee4c',N'guid10',N'Loc10',0,59),
(N'05a93b5f-7776-437c-87b8-000314a9202c',N'guid10',N'Loc10',0,87),
(N'f0d6c884-e906-4aa0-8d01-00034d8d0ea3',N'guid10',N'Loc10',0,0),
(N'0f8c0751-92ed-445e-9bfc-000416967ce6',N'guid10',N'Loc10',0,0),
(N'5733564d-cbeb-4072-bcb5-0004ad90ffc6',N'guid10',N'Loc10',64,0),
(N'bf3209a9-bbb4-4aa2-8463-0006702865a4',N'guid10',N'Loc10',72,0),
(N'289647e7-7de0-482c-8771-00088940f560',N'guid10',N'Loc10',0,0),
(N'1a3cb8cf-dcb1-4441-8ab5-0009bf036b74',N'guid10',N'Loc10',0,0),
(N'6a7a665d-0b4b-41a5-b01a-0009ee84e02b',N'guid10',N'Loc10',73,0),
(N'b75a7e85-f929-4cc6-bf3f-000aaaab33e2',N'guid10',N'Loc10',0,0),
(N'2341b029-55af-41a0-bfa3-000be8e71efe',N'guid10',N'Loc10',0,0),
(N'0bf9396e-99fc-4bf0-9a48-000e90dc0cd2',N'guid10',N'Loc10',0,0),
(N'948b91b3-5928-4eb8-ac1a-000f2d55be2a',N'guid10',N'Loc10',0,0),
(N'50edd548-7a29-40cf-a082-000f5793b5b9',N'guid10',N'Loc10',0,0),
(N'4ad8be92-ce5c-432e-a461-000ff002d0b5',N'guid10',N'Loc10',72,0),
(N'265b0d5b-223b-4da1-9d4f-00107b652ae5',N'guid10',N'Loc10',0,0),
(N'6670c15d-de83-43f4-a5fd-0010d56c574d',N'guid10',N'Loc10',0,0);
I feel like if you were to index the table, you could do this pretty simply. I created a numbered Index via location. If you have the same route of these 10 stops and the data repeats loc1-loc10 over and over, you wouldn't want to use this. You need a primary key, or a date system to make this significantly easier.
SELECT CONVERT(INT, RIGHT(Location, LEN(Location) - 3)) AS ID
,Location
,Passengerson
,PAssengersoff
INTO #IDtable
FROM #table
SELECT ID
,Location
,Passengerson
,Passengersoff
,(SELECT SUM(passengerson-passengersoff)
FROM #IDtable b
WHERE b.ID <= a.ID) AS Total
FROM #IDtable a
ORDER BY ID
this will give a result that looks like this:
Hopefully this helps you in some way.
I don't have access to 2008 R2 but this solution should work from 2005+. It's mid page on the second link provided.
;with MyData as(
select 'loc1' [location], 69 PassengersOn, 0 PassengersOff
union all select 'loc2',61,0
union all select 'loc3',333,0
union all select 'loc4',57,21
union all select 'loc5',49,29
)
SELECT
MyData.*
,RunningTotal.*
FROM MyData
cross apply (select
--SUM(PassengersOn) PassOn
--,SUM(PassengersOff) PassOff
SUM(PassengersOn) - SUM(PassengersOff) as RunningTot
from MyData MyDataApply
where MyDataApply.[location]<= MyData.[location]
) as RunningTotal
ORDER BY MyData.[location]

SQL Selecting all but newest result per id

I need to set a "waived" flag in my table for all but the newest result per id. I thought I had a query that will work here, but when I run a select on the query, I'm getting incorrect results - I saw one case where it selected both of the only two results for a particular id. I'm also getting multiple results with the same exact data.
What am I doing wrong here?
Here's my select statement:
select t.test_row_id, t.test_result_id, t.waived, t.pass, t.comment
from EV.Test_Result
join EV.Test_Result as t on EV.Test_Result.test_row_id = t.test_row_id and EV.Test_Result.start_time < t.start_time and t.device_id = 1219 and t.waived = 0
order by t.test_row_id
Here's the actual query I want to run:
update EV.Test_Result
set waived = 1
from EV.Test_Result
join EV.Test_Result as t on EV.Test_Result.test_row_id = t.test_row_id and EV.Test_Result.start_time < t.start_time and t.device_id = 1219 and t.waived = 0
If I understand this correctly, you are having problems because the Cardinality of the ON predicate returns all matching rows.
EV.Test_Result.test_row_id = t.test_row_id
and EV.Test_Result.start_time < t.start_time
This ON will compare all of the start_time values that have the same id and return every combination of result sets where start_time is lesser than the t.start_time. Clearly, this is not what you want.
and t.device_id = 1219
and t.waived = 0
This is actually a predicate (ON technically is one), but I would prefer to use this in a subquery/CTE for several reasons: You limit the number of rows SQL has to retrieve and compare.
Something like the following might be what you needed:
SELECT A.test_row_id
, A.test_result_id
, A.waived
, A.pass
, A.comment
FROM EV.Test_Result A
INNER JOIN (SELECT MAX(start_time) AS start_time
, test_row_id
FROM EV.Test_Result
WHERE device_id = 1219
AND waived = 0
GROUP BY test_row_id
) AS T ON A.test_row_id = T.test_row_id
AND A.start_time < T.start_time
ORDER BY A.test_row_id
This query then returns a 1:M relationship between the values in the ON predicate, unlike the M:M query you had run.
UPDATE:
Since I sheepishly screwed up trying to alter my Query on SO, I'll redeem myself by explaining the physical and logical orders of basic SQL Query operators:
As you know, you write a simple SELECT statement like the following:
SELECT <aggregate column>, SUM(<non-aggregate column>) AS Cost
FROM <table_name>
WHERE <column> = 'some_value'
GROUP BY <aggregate column>
HAVING SUM(<non-aggregate column>) > some_value
ORDER BY <column>
Note that if you use a aggregate function, all other columns MUST appear in the GROUP BY or another function.
Now, SQL Server requires them to be written in that order although it actually processes this logically by the following order that is worth memorizing:
FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY
There are more details found on SELECT - MSDN, but this is why any columns in the SELECT operator must be in the group by or in a aggregate function (SUM, MIN, MAX, etc)...and also why my lazy code failed on your first attempt. :/
Note also that the ORDER BY is last (technically TOP operator occurs after this), and that without it the result is not deterministic unless a function such as DENSE_RANK enforces it (thought this occurs in the SELECT statement).
Hope this helps solve the problem and better yet how SQL works. Cheers
Can you try ROW_NUMBER () function order by timestamp descending and filtering out values having ROW_NUMBER 1 ;
Below query should fetch all records per id except the latest one
I tried below query in Oracle with a table having fields : id,user_id, record_order adn timestamp and it worked :
select
<table_name_alias>.*
from
(
select
id,
user_id,
row_number() over (partition by id order by record_order desc) as record_number
from
<your_table_name>
) <table_name_alias>
where
record_number <>1;
If you are using Teradata DB, you can also try QUALIFY statement. I'm not sure if all DBs support this.
Select
table_name.*
from table_name
QUALIFY row_number() over (partition by id order by record_order desc) <>1;

SQL query join elements

I will re-write my doubt to be more easy to understand.
I have one table named SeqNumbers that have only one column of data named PossibleNumbers, that has value from 1 to 10.000.
Then I have another Table named Terminals and one of the columns have the serial numbers of the terminals. What I want is get all the SerialNumbers that not exists in the Terminals table from 1 to 10.000.
I've created the SeqNumbers table only to do this... maybe there's another solution without using it... that's fine to me.
The query I have is:
SELECT PossibleNumbers from SeqNumbers
Where PossibleNumbers NOT IN (SELECT SerialNumbers from Terminals)**
Basically I want to list ALL serial numbers of terminals that doesn't exists in the database.
This Query works fine I think... but the problem is that I don't want all results in a single column.. I want these results displayed in 4 or 5 columns.
For my purpose I can only use the results from the query like that. I cannot use programmatically methods to do that.
Hope this is more clear now... Thanks for all the help...
select x, x+1000 from tablename
Will that do it for you?
If I'm reading this right, you'd probably have to do a self join; something like:
SELECT
LeftValues.ColA,
RightValues.ColA AS ColB
FROM YourTable LeftValues
LEFT JOIN YourTable RightValues ON LeftValues.ColA = RightValues.ColA - 1000
WHERE LeftValues.ColA < 1000
Note: Use the JOIN that makes sense for you (left if you are willing to accept NULLs in ColB, inner if you only want them where both values exist)
You can use a scripting language to parse the MySQL results to format it anyway you like. Are you using PHP to access the database? If so, let me know and I can cook one up for you.
I just saw your new updated question. In this case the order of the columns will be ordered by your SELECT statement and you can also sort too. Here is an example:
SELECT Column1, Column2 FROM my_table ORDER BY Column1, Column2 ASC

Resources