How to perform a select in a single statement? - sql

I have a Sql Server 2005 table with following data:
idHearing is the primary key (identity), idCase is a foreign key that may duplicate. StartDate and StartTime specify the date and time of the event - both fields are of DateTime type (for whatever reason these are separate fields). All StartDate data has a time of 12:00:00. All StartTime data has a date of 1/1/1900. IsScheduled and IsOnCalendar are bit fields.
My challenge is to select the latest (in terms of Date/Time) hearing for each idCase. If the StartDate/StartTime are identical (as is in the rows 1 and 2), preference should be given to a row which has IsScheduled and/or IsCalendar on. If those are columns are same as well, then it does not matter which row gets returned.
To make this more complicated, I must do it all in single SELECT statement (because it must be in a view) and I have to return all the columns that you see below.
I've tried several ways, but my SQL-FU isn't strong. Any ideas?

Use:
CREATE VIEW vw_summary AS
WITH example AS (
SELECT t.idcase,
t.startdate,
t.startime,
t.isscheduled,
t.isoncalendar,
ROW_NUMBER() OVER (PARTITION BY t.idcase ORDER BY t.startdate DESC,
t.starttime DESC,
t.isscheduled DESC,
t.isoncalendar DESC) AS rank
FROM TABLE t)
SELECT e.*
FROM example e
WHERE e.rank = 1
Check & see - might tweak the ORDER BY on the ROW_NUMBER...

Pretty much the same as omg ponies answer. Row_number is your friend. I'm not entirely sure the bit fields are treated as you want, but you get the idea. As ever, it's always best to be explicit with the fields you are selecting, but I'm lazy.
create table #table
(
idHearing int,
idCase int,
startDate datetime,
starttime datetime,
isscheduled bit,
isoncalendar bit
);
insert into #table values(1,1,'8/2/2010','3:30:00 PM',1,1)
insert into #table values(2,1,'8/2/2010','3:30:00 PM',1,0)
insert into #table values(3,2,'8/3/2010','5:30:00 PM',1,1)
insert into #table values(4,2,'8/4/2010','9:30:00 PM',1,1)
insert into #table values(5,3,'8/2/2010','3:00:00 PM',1,1)
select * from
(
select
row_number()
over
(partition by idcase order by
startdate desc,
starttime desc,
isscheduled desc,
isoncalendar desc
) idCasePosition,
*
from #table
) x
where idCasePosition=1
drop table #table

Related

Minus values from the same column

I have a table with 2 columns. one contains the user's ID and the other contains the datetime whenever that user logged into the application.
I want to create a custom computation where the datetime value from the same column subtracts each other, as the latest datetime will minus the previous datetime of that latest datetime, and keeps going like that til the first-time login datetime of that user.
Right now I have no clue on how to code this computation so I really need your help and would very appreciate it.
Sample date:
I fiddled around in the AdventureWorks db and might have found a way to get what you are looking for(although I am new to this, so someone with more experience and knowledge might have a better idea). But hopefully this provides some starting point. I created 2 CTEs with Row_Number, second CTE had Row_Number-1 as it's count. Then joined those two CTEs and did a datediff on the event_datetimes.
WITH Example_CTE (Row, UserID, Event_datetime)
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Row
,UserID
,Event_datetime
FROM table
ORDER BY UserID,Event_datetime DESC
)
,
Example_CTE2 (Row, UserID, Event_datetime)
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL))-1 AS Row
,UserID
,Event_datetime
FROM table
ORDER BY UserID, Event_datetime DESC
)
SELECT Example_CTE.UserID
,DATEDIFF(day, Example_CTE.Event_datetime, Example_CTE2.Event_datetime) as TimeDiff
FROM Example_CTE
left outer join Example_CTE2 on Example_CTE.row = Example_CTE2.Row

Pick Max Date from Table

I have a table variable defined thus
DECLARE #DatesTable TABLE
(
Id uniqueidentifier,
FooId uniqueidentifier,
Date date,
Value decimal (26, 10)
)
Id is always unique but FooId is duplicated throughout the table. What I would like to do is to select * from this table for each unique FooId having the max(date). So, if there are 20 rows with 4 unique FooIds then I'd like 4 rows, picking the row for each FooId where the date is the largest.
I've tried using group by but I kept getting errors about various fields not being in the select clause etc.
Use a common table expression with row_number():
;WITH cte AS
(
SELECT Id, FooId, Date, Value,
ROW_NUMBER() OVER(PARTITION BY FooId ORDER BY Date DESC) As rn
FROM #DatesTable
)
SELECT Id, FooId, Date, Value
FROM cte
WHERE rn = 1
Often the most efficient method is a correlated subquery:
select dt.*
from #DatesTable dt
where dt.date = (select max(dt2.date) from #DatesTable dt2 where dt2.fooid = dt.fooid);
However, for this to be efficient, you need an index on (fooid, date). In more recent versions of SQL Server, you can have indexes on table variables. In earlier versions, you can do this using a primary key.

Insert data into temporary Table

I'm using SQL Server and I'm trying to build a temporary Table where it have a column retrieved by an currently exciting table and insert in each row a date.
For example I have
select NumberID into #Table0
from Table1
where numcue in [conditions]
In the new Table0 I have the NumberID ordered by a certain criteria. But in that exact same order I want to introduce a date for each row.
Is there any way to do it without using a CREATE TABLE, or INSERT ( I don't have permissions for that)
Thanks in advance
-------EDITION--- (MORE INFO)
Maybe I wasn't clear about it, long story short is that I have IDNUMBER in the TABLE1 on my Datawarehouse (10k+rows), but it have 20 dates for each IDNUMBER.
In an Excel I have the date I need to retrieve for each IDNUMBER, but I don't know how to retrieve that exact info directly with a QUERY. And the dates doesn't have a criteria is just random date for each IDNUMBER so I can't code it directly.
So what I was trying to do, is put each IDNUMBER with the date of the Excel in a temporary Table and then keep looking info with that
Hope this help to explain a little further
Thanks in advance and for all the current answers
So you mean something like this?
select NumberID, GETDATE() AS DateColumn into #Table0
from Table1
where numcue in [conditions]
I think you can do it by using a CTE (Common Table Expression) to find the row number for your ID's.
I'm not sure if this is the case, but I've understood you want to increment the date for each row, e.g.:
NumberID|Date
1 |2018-01-01
3 |2018-01-02
12 |2018-01-03
25 |2018-01-04
In that case, I've supplied some code that uses the sys_objects table as an example:
DECLARE #FirstDate DATE = '20180101'
;WITH CTE
AS
(
SELECT TOP (100) PERCENT object_id, ROW_NUMBER() OVER (ORDER BY object_id ASC) AS RowNumber
FROM master.sys.objects
ORDER BY object_id
)
SELECT object_id, DATEADD(dd, RowNumber-1, #FirstDate) AS Date, RowNumber
FROM CTE;
You can ignore the RowNumber column - I've just added for you to understand that it is a sequence.
For you case in particular, I think this code should work - remember to specify your initial date:
DECLARE #FirstDate DATE = '20180101'
;WITH CTE
AS
(
SELECT TOP (100) PERCENT NumberID, ROW_NUMBER() OVER (ORDER BY NumberID ASC) AS RowNumber
FROM Table1
WHERE numcue IN [conditions]
)
SELECT NumberID, DATEADD(dd, RowNumber-1, #FirstDate) AS Date
FROM CTE;

How to select just the third or fourth row in SQL Server

I am having a little bit of trouble figuring out a way to select just the third or fourth row in a query I am writing, any help would be greatly appreciated.
This is an example of the code I came up with, this however only selects the first row.
Left Outer Join (select ap_attachments.ap_table_key, ap_description, ap_creation_date, ap_creation_time, ap_file_name, ap_attach_id
from ap_attachments
inner join (select Min(ap_attachment_id) ap_attach_id, ap_table_key
from ap_attachments
where ap_file_name like '%jpg%'
group by ap_table_key) C
On ap_attachments.ap_attachment_id = C.ap_attach_id) apImgThree_attach
On apImgTwo_attach.ap_table_key = order_link.to_order_id
You can do this with the ROW_NUMBER() function:
select ap_attachment_id, ap_table_key,ROW_NUMBER() OVER(PARTITION BY ap_table_key ORDER BY ap_attachment_id) AS RN
from ap_attachments
where ap_file_name like '%jpg%'
Then you can specify which row you'd like to return using the RN value. This may require some adapting depending on your source data, the DENSE_RANK() function may be more appropriate.
The ROW_NUMBER() function assigns a number to each row. PARTITION BY is optional, but used to start the numbering over for each value in that group, ie: if you PARTITION BY Some_Date then for each unique date value the numbering would start over at 1. ORDER BY of course is used to define how the counting should go, and is required in the ROW_NUMBER() function.
Look up the docs on lead and lag. You can also use the PARTITION clause to create the window within a specific date, for example;
declare #table table(
[flower] [sysname]);
insert into #table
([flower])
values (N'rose'),
(N'tulip'),
(N'chamomile'),
(N'lily');
select [flower] from #table order by [flower];
select [flower]
, lag ([flower]
, 1
, 0)
over (
order by [flower] desc) as [previous_flower]
, lead ([flower]
, 1
, 0)
over (
order by [flower] desc) as [next_flower]
from #table;

Retrieving most recent data in SQL

Total disclosure: I'm a SQL beginner.
I have a data set of certain accounting and governance metrics for US companies. It has about 15 columns and roughly 18 million rows. Each row is a unique combination of company, date and metric being measured. The columns include certain identifiers like isin number, ticker symbol, etc, the date the metric was released, the metric description, and the metric itself.
What I'm trying to do is write a query that will yield the NEWEST values for a certain metric for all companies. In my hopeless search over the past few days I've come to think that the GROUP BY clause may be what I'm looking for. However, it doesn't seem to do exactly what I need. I've got it working with just 2 columns: isin number (company identifier), and date. In other words, I can spit out a list that shows the most recent date for each company, but I'm not sure how to add more columns to this, how to specify what metric to look at.
Any guidance would be appreciated, even if it's just pointing me in the right direction towards what kind of commands I should be looking into.
Thanks!
EDIT: Wow. Thanks for the quick and thorough replies. And point taken on the clarity and example data sets/starting query. Update: I think I have it working. Here's what I used:
SELECT a1.["id_isin_number"], a1.["metric_description"], a1.["date_period_ends"], a1.["company_metric_value"], a2.maxdate
FROM [AGR Metrics].[dbo].[Audit_Integrity_Metric_Data_File_NA Original_0] a1
INNER JOIN (
SELECT a2.["id_isin_number"], MAX(a2.["date_period_ends"]) AS maxdate
FROM [AGR Metrics].[dbo].[Audit_Integrity_Metric_Data_File_NA Original_0] a2
GROUP BY a2.["id_isin_number"]
) a2
ON a1.["date_period_ends"] = a2.maxdate
AND a1.["id_isin_number"] = a2.["id_isin_number"]
WHERE a1.["metric_description"] = '"Litigation: Class Action"'
I'm looking over the responses now to make sure I'm doing this as efficiently as possible.
You can use the ROW_NUMBER() function for this (if using SQL Server 2005 or newer):
SELECT *
FROM (SELECT *,ROW_NUMBER() OVER(PARTITION BY isin ORDER BY [date] DESC) AS RowRank
FROM YourTable
)sub
WHERE RowRank = 1
Just list out the fields you want in place of * if you don't want them all returned.
The ROW_NUMBER() function adds a number to each row, PARTITION BY is optional and is used to define a group for which numbering will start over at 1, in this case, you want the most recent for each value of isin so we PARTITION BY that. ORDER BY is required and defines the order of the numbering, in this case by date.
Your current query can also be used, but the ROW_NUMBER() method is simpler and more efficient:
SELECT a.*
FROM YourTable a
JOIN (SELECT isin, MAX([date])
FROM YourTable
GROUP BY isin
)b
ON a.isin = b.isin
AND a.[date] = b.[date]
Well as you quote the date the metric was released , So you can use it to sort your table using Order By .
This is a very basic example which can be used to simply sort data and selecting top 1 value.
Please refer This
CREATE TABLE trialOne (
Id INT NULL,
NAME VARCHAR(50) NULL,
[Date] DATETIME NULL
)
SELECT * FROM dbo.ETProgram
INSERT INTO trialone VALUES(1,'john','2009-01-06 11:39:51.827')
INSERT INTO trialone VALUES(2,'joseph','2010-01-06' )
INSERT INTO trialone VALUES(3,'Ajay','2009-05-06' )
INSERT INTO trialone VALUES(4,'Dave','2009-11-06' )
INSERT INTO trialone VALUES(5,'jonny','2004-01-06')
INSERT INTO trialone VALUES(6,'sunny','2005-01-06')
INSERT INTO trialone VALUES(7,'elle','2013-01-06' )
INSERT INTO trialone VALUES(8,'mac','2012-01-06' )
INSERT INTO trialone VALUES(8,'Sam','2008-01-06' )
INSERT INTO trialone VALUES(10,'xxxxx','2013-08-06')
SELECT TOP(1)name FROM trialone ORDER BY Date DESC