How to get single result when a column has the same value but the second column have different value - sql

I have this table
Id VendorId ClaimRequestDate
1 5 2017-12-14 00:00:00.000
2 5 2018-02-02 00:00:00.000
7 5 2018-02-07 11:08:25.257
I want my result to show only the latest date for each VendorId starting from date later than 2 Feb 2018
what I've done now
SELECT DISTINCT
[Project1].[Id] AS [Id],
[Project1].[VendorId] AS [VendorId],
[Project1].[ClaimRequestDate] AS [ClaimRequestDate]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[VendorId] AS [VendorId],
[Extent1].[ClaimRequestDate] AS [ClaimRequestDate]
FROM [dbo].[Claim] AS [Extent1]
WHERE [Extent1].[ClaimRequestDate] >= '2018-02-02 00:00:00.000'
) AS [Project1]
ORDER BY [Project1].[ClaimRequestDate] DESC
But my result is
Id VendorId ClaimRequestDate
7 5 2018-02-07 11:08:25.257
2 5 2018-02-02 00:00:00.000
Can someone help me with this

There are tree problem in your query. one is
WHERE [Extent1].[ClaimRequestDate] >= '2018-02-02 00:00:00.000'
Row is >= should be ">" second one is your query gain all rows from date later than 2018-02-02 If a vendorId has more than a value Query would return you can try this
SELECT * FROM Claim c
where ClaimRequestDate IN (select MAX(ClaimRequestDate) from claim c1
where c.vendorId =c1.vendorId and c1.Claimrequestdate >'2018.02.02')
Third is this query when your vendorId has more than same max(Claimrequestdate) would return all of them
Id VendorId ClaimRequestDate
1 5 2017-12-14 00:00:00.000
2 5 2018-02-02 00:00:00.000
7 5 2018-02-07 11:08:25.257
8 5 2018-02-07 11:08:25.257
returns
Id VendorId ClaimRequestDate
7 5 2018-02-07 11:08:25.257
8 5 2018-02-07 11:08:25.257
For these reason I suggest this query for use
SELECT * FROM Claim c
where CAST(ClaimRequestDate AS VARCHAR)+ CAST(ID AS VARCHAR) IN (select
MAX(CAST(ClaimRequestDate AS VARCHAR)+ CAST(ID AS VARCHAR)) from claim c1
where c.vendorId =c1.vendorId and c1.Claimrequestdate >'2018.02.02'
)

Try the following SQL:
select aa.* from [Claim] as aa inner join
(
select [VendorId], max([Id]) as maxId from [Claim]
where [ClaimRequestDate] >= '2018-02-03 00:00:00'
group by [VendorId]
) as bb on aa.[Id] = bb.[maxId]

Related

Get max date for each from either of 2 columns

I have a table like below
AID BID CDate
-----------------------------------------------------
1 2 2018-11-01 00:00:00.000
8 1 2018-11-08 00:00:00.000
1 3 2018-11-09 00:00:00.000
7 1 2018-11-15 00:00:00.000
6 1 2018-12-24 00:00:00.000
2 5 2018-11-02 00:00:00.000
2 7 2018-12-15 00:00:00.000
And I am trying to get a result set as follows
ID MaxDate
-------------------
1 2018-12-24 00:00:00.000
2 2018-12-15 00:00:00.000
Each value in the id columns(AID,BID) should return the max of CDate .
ex: in the case of 1, its max CDate is 2018-12-24 00:00:00.000 (here 1 appears under BID)
in the case of 2 , max date is 2018-12-15 00:00:00.000 . (here 2 is under AID)
I tried the following.
1.
select
g.AID,g.BID,
max(g.CDate) as 'LastDate'
from dbo.TT g
inner join
(select AID,BID,max(CDate) as maxdate
from dbo.TT
group by AID,BID)a
on (a.AID=g.AID or a.BID=g.BID)
and a.maxdate=g.CDate
group by g.AID,g.BID
and 2.
SELECT
AID,
CDate
FROM (
SELECT
*,
max_date = MAX(CDate) OVER (PARTITION BY [AID])
FROM dbo.TT
) AS s
WHERE CDate= max_date
Please suggest a 3rd solution.
You can assemble the data in a table expression first, and the compute the max for each value is simple. For example:
select
id, max(cdate)
from (
select aid as id, cdate from t
union all
select bid, cdate from t
) x
group by id
You seem to only care about values that are in both columns. If this interpretation is correct, then:
select id, max(cdate)
from ((select aid as id, cdate, 1 as is_a, 0 as is_b
from t
) union all
(select bid as id, cdate, 1 as is_a, 0 as is_b
from t
)
) ab
group by id
having max(is_a) = 1 and max(is_b) = 1;

Subtract subsequent row from previous row based on User

I have the following data and I want to subtract current row from previous row based on the UserID. I tried the code below is not given me what I want
DECLARE #DATETBLE TABLE (UserID INT, Dates DATE)
INSERT INTO #DATETBLE VALUES
(1,'2018-01-01'), (1,'2018-01-02'), (1,'2018-01-03'),(1,'2018-01-13'),
(2,'2018-01-15'),(2,'2018-01-16'),(2,'2018-01-17'), (5,'2018-02-04'),
(5,'2018-02-05'),(5,'2018-02-06'),(5,'2018-02-11'), (5,'2018-02-17')
;with cte as (
select UserID,Dates, row_number() over (order by UserID) as seqnum
from #DATETBLE t
)
select t.UserID,t.Dates, datediff(day,tprev.Dates,t.Dates)as diff
from cte t left outer join
cte tprev
on t.seqnum = tprev.seqnum + 1;
Current Output
UserID Dates diff
1 2018-01-01 NULL
1 2018-01-02 1
1 2018-01-03 1
1 2018-01-13 10
2 2018-01-15 2
2 2018-01-16 1
2 2018-01-17 1
5 2018-02-04 18
5 2018-02-05 1
5 2018-02-06 1
5 2018-02-11 5
5 2018-02-17 6
My Expected Output
UserID Dates diff
1 2018-01-01 NULL
1 2018-01-02 1
1 2018-01-03 1
1 2018-01-13 10
2 2018-01-15 NULL
2 2018-01-16 1
2 2018-01-17 1
5 2018-02-04 NULL
5 2018-02-05 1
5 2018-02-06 1
5 2018-02-11 5
5 2018-02-17 6
Your tag (sql-server-2008) suggests me to use APPLY :
select t.userid, t.dates, datediff(day, t1.dates, t.dates) as diff
from #DATETBLE t outer apply
( select top (1) t1.*
from #DATETBLE t1
where t1.userid = t.userid and
t1.dates < t.dates
order by t1.dates desc
) t1;
If you have SQL Server version 2012 or higher, you could use LAG() with a partition by UserID:
SELECT UserID
, DATEDIFF(dd,COALESCE(LAG_DATES, Dates), Dates) as diff
FROM
(
SELECT UserID
, Dates
, LAG(Dates) OVER (PARTITION BY UserID ORDER BY Dates) as LAG_DATES
FROM #DATETBLE
) exp
This will give you a 0 value instead of a NULL value for the first date in the sequence though.
Since you tagged the post with SQL Server 2008, however, you may need to use a method that doesn't rely on this windowed function.

How to write a query that would leave 1 row out

I have a set of data that looks like this I want to remove one row for each of the debnrs that has a p in it for type. I don't care which one. The two rows with P in the type are identical except for the date. How would I select just one with a P in the type.
debnr docno date type num amount
4 NULL 2013-08-29 07:26:25.000 P 1761 -12
4 NULL 2013-09-12 00:00:00.000 P 1761 -12
4 168371 2013-08-29 00:00:00.000 I 168371 12
5 NULL 2013-10-11 09:24:58.000 P 7287 -24
5 NULL 2013-10-14 00:00:00.000 P 7287 -24
5 170366 2013-10-11 00:00:00.000 I 170366 24
6 NULL 2013-10-24 00:00:00.000 P 4023 -465
6 NULL 2013-10-24 09:42:18.000 P 4023 -465
6 171095 2013-10-24 00:00:00.000 I 171095 465
7 NULL 2013-12-16 00:00:00.000 P 171502 -394.2
7 NULL 2013-12-16 00:00:00.000 P 6601 -394.2
7 171502 2013-10-30 00:00:00.000 I 171502 394.2
how would I get it to look like this.
4 NULL 2013-09-12 00:00:00.000 P 1761 -12
4 168371 2013-08-29 00:00:00.000 I 168371 12
5 NULL 2013-10-14 00:00:00.000 P 7287 -24
5 170366 2013-10-11 00:00:00.000 I 170366 24
6 NULL 2013-10-24 09:42:18.000 P 4023 -465
6 171095 2013-10-24 00:00:00.000 I 171095 465
7 NULL 2013-12-16 00:00:00.000 P 6601 -394.2
7 171502 2013-10-30 00:00:00.000 I 171502 394.2
Shot in the dark:
select
debnr,
docno,
max(date),
type,
num,
amount
from magical_table
group by
debnr,
docno,
type,
num,
amount
You could GROUP and use an aggregate given your sample above, if however the amount field weren't identical, for instance, then you could use the ROW_NUMBER() function for this to avoid needing an aggregate:
;WITH cte AS (SELECT *
,CASE WHEN TYPE = 'P' THEN ROW_NUMBER() OVER(PARTITION BY debnr ORDER BY (SELECT 1))
ELSE 0
END AS RN
FROM Table1)
SELECT *
FROM cte
WHERE RN <= 1
Demo: SQL Fiddle
The ORDER BY (SELECT 1) could be changed to any field, that's just one way to get an arbitrary result if you don't want a min/max.
Want you line with type "I" ungrouped ?
select debnr, docno, max(date), type, num, amount
from magical_table
where type = "P"
group by debnr, docno, type, num, amount
UNION
select debnr, docno, date, type, num, amount
from magical_table
where type = "I"

SQL First Time In Last Time Out (Transact-SQL..preferrably)

I have the following table which contains all the time in and time out of people:
CREATE TABLE test (
timecardid INT
, trandate DATE
, employeeid INT
, trantime TIME
, Trantype VARCHAR(1)
, Projcode VARCHAR(3)
)
The task is to get all the earliest trantime with trantype A (perhaps using MIN) and the latest trantime with trantype Z (Using Max), all of which in that trandate (ie. trantype A for july 17 is 8:00 AM and trantype Z for july 17 is 7:00PM).
the problem is, the output should be in the same format as the table where it's coming from, meaning that I have to leave this data and filter out the rest (that aren't the earliest and latest in/out for that date, per employee)
My current solution is to use two different select commands to get all earliest, then get all the latest. then combine them both.
I was wondering though, is there a much simpler, single string solution?
Thank you very much.
EDIT (I apologize, here is the sample. Server is SQL Server 2008):
Timecardid | Trandate | employeeid | trantime | trantype | Projcode
1 2013-04-01 1 8:00:00 A SAMPLE1
2 2013-04-01 1 9:00:00 A SAMPLE1
3 2013-04-01 2 7:00:00 A SAMPLE1
4 2013-04-01 2 6:59:59 A SAMPLE1
5 2013-04-01 1 17:00:00 Z SAMPLE1
6 2013-04-01 1 17:19:00 Z SAMPLE1
7 2013-04-01 2 17:00:00 Z SAMPLE1
8 2013-04-02 1 8:00:00 A SAMPLE1
9 2013-04-02 1 9:00:00 A SAMPLE1
10 2013-04-02 2 7:00:58 A SAMPLE1
11 2013-04-02 2 18:00:00 Z SAMPLE1
12 2013-04-02 2 18:00:01 Z SAMPLE1
13 2013-04-02 1 20:00:00 Z SAMPLE1
Expected Results (the earliest in and the latest out per day, per employee, in a select command):
Timecardid | Trandate | employeeid | trantime | trantype | Projcode
1 2013-04-01 1 8:00:00 A SAMPLE1
4 2013-04-01 2 6:59:59 A SAMPLE1
6 2013-04-01 1 17:19:00 Z SAMPLE1
7 2013-04-01 2 17:00:00 Z SAMPLE1
8 2013-04-02 1 8:00:00 A SAMPLE1
10 2013-04-02 2 7:00:58 A SAMPLE1
12 2013-04-02 2 18:00:01 Z SAMPLE1
13 2013-04-02 1 20:00:00 Z SAMPLE1
Thank you very much
Perhaps this is what you're looking for:
select
t.*
from
test t
where
trantime in (
(select min(trantime) from test t1 where t1.trandate = t.trandate and trantype = 'A'),
(select max(trantime) from test t2 where t2.trandate = t.trandate and trantype = 'Z')
)
Changing my answer to account for the "per employee" requirement:
;WITH EarliestIn AS
(
SELECT trandate, employeeid, min(trantime) AS EarliestTimeIn
FROM test
WHERE trantype = 'A'
GROUP BY trandate, employeeid
),
LatestOut AS
(
SELECT trandate, employeeid, max(trantime) AS LatestTimeOut
FROM test
WHERE trantype = 'Z'
GROUP BY trandate, employeeid
)
SELECT *
FROM test t
WHERE
EXISTS (SELECT * FROM EarliestIn WHERE t.trandate = EarliestIn.trandate AND t.employeeid = EarliestIn.employeeid AND t.trantime = EarliestIn.EarliestTimeIn)
OR EXISTS (SELECT * FROM LatestOut WHERE t.trandate = LatestOut.trandate AND t.employeeid = LatestOut.employeeid AND t.trantime = LatestOut.LatestTimeOut)
Assuming timecardid column is PK or unique, and if I understand it correctly, I would do something like
DECLARE #date DATE
SET #date = '2013-07-01'
SELECT
T0.*
FROM
(SELECT DISTINCT employeeid FROM test) E
CROSS APPLY (
SELECT TOP 1
T.timecardid
FROM
test T
WHERE
T.trandate = #date
AND T.Trantype = 'A'
AND T.employeeid = E.employeeid
ORDER BY T.trantime
UNION ALL
SELECT TOP 1
T.timecardid
FROM
test T
WHERE
T.trandate = #date
AND T.Trantype = 'Z'
AND T.employeeid = E.employeeid
ORDER BY T.trantime DESC
) V
JOIN test T0 ON T0.timecardid = V.timecardid
Appropriate indexes should be set for the table, if you aware of performance.
If you're using SQL server 2012, you can use LAG/LEAD to find the max and min rows in a fairly concise way;
WITH cte AS (
SELECT *,
LAG(timecardid) OVER (PARTITION BY trandate,employeeid,trantype ORDER BY trantime) lagid,
LEAD(timecardid) OVER (PARTITION BY trandate,employeeid,trantype ORDER BY trantime) leadid
FROM test
)
SELECT timecardid,trandate,employeeid,trantime,trantype,projcode
FROM cte
WHERE trantype='A' AND lagid IS NULL
OR trantype='Z' AND leadid IS NULL;
An SQLfiddle to test with.
I would use ROW_NUMBER to sort out the rows you want to select:
;with Ordered as (
select *,
ROW_NUMBER() OVER (PARTITION BY Trandate,employeeid,trantype
ORDER BY trantime ASC) as rnEarly,
ROW_NUMBER() OVER (PARTITION BY Trandate,employeeid,trantype
ORDER BY trantime DESC) as rnLate
from
Test
)
select * from Ordered
where
(rnEarly = 1 and trantype='A') or
(rnLate = 1 and trantype='Z')
order by TimecardId
(SQLFiddle)
It produces the results you've requested, and I think it's quite readable. The reason that trantype is included in the PARTITION BY clauses is so that A and Z values receive separate numbering.

SQL Server - Count events that happen from 15 min to 14 days from base time

I am using SQL Server 2005. I am trying to count the number of repeats that would fall in between 15 minuites and 14 days when the Client and Type are the same.
The Table [Interactions] looks like:
eci_date user_ID Type Client
2012-05-01 10:29:59.000 user1 12 14
2012-05-01 10:35:04.000 user1 3 15
2012-05-01 10:45:14.000 user3 4 14
2012-05-01 11:50:22.000 user1 5 15
------------------------------------------
2012-05-02 10:30:28.000 user2 12 14
2012-05-02 10:48:59.000 user5 12 14
2012-05-02 10:52:23.000 user2 12 15
2012-05-02 12:49:45.000 user8 3 14
------------------------------------------
2012-05-03 10:30:47.000 user4 5 15
2012-05-03 10:35:00.000 user6 4 12
2012-05-03 10:59:10.000 user7 4 12
I would like the output to look like:
eci_date Type Total_Calls Total_Repeats
2012-05-01 12 1 2
2012-05-01 3 1 0
2012-05-01 4 1 0
2012-05-01 5 1 1
---------------------------------------------
2012-05-02 12 3 0
2012-05-02 3 1 0
---------------------------------------------
2012-05-03 4 2 1
2012-05-03 5 1 0
So there would be 2 repeats because client 14 called in 2 times after the first date they called in because Client and Type must be the same and because I need to filter by day.
Thank You.
With Metrics As
(
Select T1.Client, T1.Type
, Min(eci_Date) As FirstCallDate
From Table1 As T1
Group By T1.Client, T1.Type
)
Select DateAdd(d, DateDiff(d,0,T1.eci_date), 0) As [Day], Type, Count(*) As TotalCalls
, (
Select Count(*)
From Table1 As T2
Join Metrics As M2
On M2.Client = T2.Client
And M2.Type = T2.Type
Where T2.eci_Date >= DateAdd(mi,15,M2.FirstCallDate)
And T2.eci_date <= DateAdd(d,15,M2.FirstCallDate)
And DateAdd(d, DateDiff(d,0,T1.eci_date), 0) = DateAdd(d, DateDiff(d,0,T2.eci_date), 0)
) As Total_Repeats
From Table1 As T1
Group By DateAdd(d, DateDiff(d,0,T1.eci_date), 0), Type
Order By [Day] Asc, Type Desc
SQL Fiddle
Your question is vague, so I'm interpreting it to mean the following:
* The "total_count" column is the number of distinct users on a given day
* The number of repeats is the number of calls after the first one in the next 14 days
The following query accomplishes this:
select eci_date, count(distinct id) as numusers, count(*) as Total_repeats
from
(
select cast(eci_date as date) as eci_date,
id,
count(*) as total,
min(eci_date) as firstcall
from table t
group by cast(eci_date as date), user_id
) t
left outer join table t2
on t.user_id = t2.user_id
and t2.eci_date between firstcall and dateadd(day, 14, firstcall)
and t2.eci_date <> firstcall
group by eci_date
Note this uses the syntax cast(<datetime> as date) to extract the date portion from a datetime.