SQL query to fetch repeat column values within time frame - sql-server

I have an eCommerce website where I am getting lot of fraud orders.. I'd like to pull out those Order_No.
Here is my query
SELECT
O.Order_No, O.Customer_ID, O.DateOrdered, O.IPAddress,
C.FirstName, C.LastName, CD.nameoncard
FROM
Order_No O
INNER JOIN
CardData CD ON O.card_id = CD.id
INNER JOIN
Customers C ON O.customer_id = C.customer_id
ORDER BY
O.order_no desc
Here's the criteria I want to follow:
If the customer_id repeats more than once in 6hrs
If the IPAddress repeats more than once in 6hrs
If the Lastname is NOT found in Nameoncard
Can someone help please?

can you try this
WITH Tmp (Order_No, Customer_id, DateOrdered, IPAddress, FirstName, LastName, NameOnCard)
AS
(
SELECT Ord.Order_No, Ord.Customer_Id, Ord.DateOrdered, Ord.IPAddress,
Cust.FirstName, Cust.LastName, CustData.NameOnCard
FROM Order_No Ord
INNER JOIN Customers Cust
ON
Cust.Customer_Id = Ord.Customer_Id
INNER JOIN
CardData CustData
ON CustData.Id = Ord.Card_Id
)
SELECT DISTINCT a.*
FROM Tmp a
INNER JOIN Tmp b
ON a.Order_No <> b.Order_No
AND a.Customer_Id = b.Customer_Id
WHERE DATEDIFF(hour, a.DateOrdered, b.DateOrdered) >= 6
UNION
SELECT DISTINCT c.*
FROM Tmp c
INNER JOIN Tmp d
ON c.Order_No <> d.Order_No
AND c.IPAddress = d.IPAddress
WHERE DATEDIFF(hour, c.DateOrdered, d.DateOrdered) >= 6
UNION
SELECT DISTINCT e.*
FROM Tmp e
WHERE ISNULL(e.NameOnCard,'') = ''

here is the query:
select * from
(
select b.order_no,b.dateordered,a.customer_id, C.FirstName, C.LastName, cd.nameoncard from order_no as a
left join order_no as b on a.customer_id=b.customer_id
inner join carddata as cd on b.customer_id=cd.customer_id
INNER JOIN Customers C ON b.customer_id = C.customer_id
where a.order_no < b.order_no
and datediff(hour,a.dateordered,b.dateordered) between 0 and 6
union
select b.order_no,b.dateordered,a.customer_id, C.FirstName, C.LastName, cd.nameoncard from order_no as a
left join order_no as b on a.IPAddress=b.IPAddress
inner join carddata as cd on b.customer_id=cd.customer_id
INNER JOIN Customers C ON b.customer_id = C.customer_id
where a.order_no < b.order_no
and datediff(hour,a.dateordered,b.dateordered) between 0 and 6
union
select a.order_no,a.dateordered,a.customer_id, C.FirstName, C.LastName, cd.nameoncard from order_no as a
inner join carddata as cd on a.customer_id=cd.customer_id
INNER JOIN Customers C ON a.customer_id = C.customer_id
where charindex(C.LastName,cd.nameoncard) = 0
) as abc

Related

Subquery and NOT NULL

I need some help with a subquery. My test column sometimes comes back NULL and if so I want to filter those out of my results set.
My stored procedure looks like this
SELECT
pl.Id AS Id,
pl.Name AS Name,
f.[Url] AS PrimaryImageUrl,
up.Id AS MemberId,
up.ProfessionalName,up.
AvatarUrl,
test = (SELECT
c.Id AS Id,
c.Name AS Name,
c.ContentImageUrl AS ImageUrl,
c.Price AS Price,
c.BPM AS BPM,
f.Id AS 'File.Id',
f.Url AS 'File.Name',
TotalCount = COUNT (c.Id) OVER()
FROM
dbo.Content c
INNER JOIN
dbo.PlayListContents pm ON c.Id = pm.ContentId
AND pm.PlaylistId = pl.Id
INNER JOIN
dbo.Files f ON c.ContentFileId = f.Id
FOR JSON PATH),
TotalCount = COUNT(1) OVER()
FROM
dbo.Playlist pl
INNER JOIN
dbo.UserProfiles up ON pl.UserId = up.UserId
INNER JOIN
[dbo].[Files] AS f ON pl.[PrimaryImageId] = f.[Id]
WHERE
(pl.Name LIKE '%' + #searchInput + '%')
AND test IS NOT NULL
Why is this last line, AND test IS NOT NULL invalid? I need my result set to have all results with test being NOT NULL
Try this
SELECT * FROM
(Select pl.Id as Id
,pl.Name as Name
,f.[Url] as PrimaryImageUrl
,up.Id as MemberId
,up.ProfessionalName
,up.AvatarUrl
,test = ( select c.Id as Id
,c.Name as Name
,c.ContentImageUrl as ImageUrl
,c.Price as Price
,c.BPM as BPM
,f.Id as 'File.Id'
,f.Url as 'File.Name'
,TotalCount = count(c.Id)Over()
from dbo.Content c
inner join dbo.PlayListContents pm on c.Id = pm.ContentId and pm.PlaylistId = pl.Id
inner join dbo.Files f on c.ContentFileId = f.Id
for json path)
--,TotalCount = COUNT(1) OVER()
from dbo.Playlist pl
inner join dbo.UserProfiles up on pl.UserId = up.UserId
inner join [dbo].[Files] as f ON pl.[PrimaryImageId] = f.[Id]
where ( pl.Name LIKE '%' + #searchInput + '%')) a
WHERE a.test IS NOT NULL
Columns in the SELECT are not available in the WHERE, due to SQL's logical order of operations.
Instead, place the value in CROSS APPLY, then filter after that:
SELECT
pl.Id AS Id,
pl.Name AS Name,
f.[Url] AS PrimaryImageUrl,
up.Id AS MemberId,
up.ProfessionalName,up.
AvatarUrl,
v.test,
TotalCount = COUNT(1) OVER()
FROM
dbo.Playlist pl
INNER JOIN
dbo.UserProfiles up ON pl.UserId = up.UserId
INNER JOIN
[dbo].[Files] AS f ON pl.[PrimaryImageId] = f.[Id]
CROSS APPLY (
SELECT test =
(SELECT
c.Id AS Id,
c.Name AS Name,
c.ContentImageUrl AS ImageUrl,
c.Price AS Price,
c.BPM AS BPM,
f.Id AS 'File.Id',
f.Url AS 'File.Name',
TotalCount = COUNT (c.Id) OVER()
FROM
dbo.Content c
INNER JOIN
dbo.PlayListContents pm ON c.Id = pm.ContentId
AND pm.PlaylistId = pl.Id
INNER JOIN
dbo.Files f ON c.ContentFileId = f.Id
FOR JSON PATH
)
) v
WHERE
(pl.Name LIKE '%' + #searchInput + '%')
AND v.test IS NOT NULL;

WHERE is not null for correlated subquery

My proc looks like this :
Select pl.Id as Id,
pl.Name as Name,
f.[Url] as PrimaryImageUrl,
up.Id as MemberId,
up.ProfessionalName,
up.AvatarUrl,
(
select c.Id as Id,
c.Name as Name,
c.ContentImageUrl as ImageUrl,
c.Price as Price,
c.BPM as BPM,
f.Id as 'File.Id',
f.Url as 'File.Name',
g.Id as 'Genre.Id',
g.Name as 'Genre.Name',
kt.Id as 'KeyType.Id',
kt.Name as 'KeyType.Name',
tt.Id as 'TrackType.Id',
tt.Name as 'TrackType.Name',
TotalCount = count(c.Id) Over ()
from dbo.Content c
inner join dbo.PlayListContents pm
on c.Id = pm.ContentId
and pm.PlaylistId = pl.Id
inner join dbo.Files f
on c.ContentFileId = f.Id
inner join dbo.Genres g
on c.GenreTypeId = g.Id
inner join dbo.KeyType kt
on c.KeyTypeId = kt.Id
inner join dbo.TrackType tt
on tt.Id = c.TrackTypeId
Where (NOT EXISTS (
SELECT b.Bpm
FROM #Bpm AS b
WHERE b.Bpm IS NOT NULL)
OR c.Bpm IN (SELECT * FROM #Bpm)
)
for json path
) AS Content,
TotalCount = COUNT(1) OVER ()
from dbo.Playlist pl
inner join dbo.UserProfiles up
on pl.UserId = up.UserId
inner join [dbo].[Files] as f
ON pl.[PrimaryImageId] = f.[Id]
where (pl.Name LIKE '%' + #searchInput + '%')
Using this proc I sometimes get results with Content column at NULL.
why can't I add WHERE Content IS NOT NULL and have my results come back with no rows with NULL at Content column?

how do i use a temporary date table combine with three other Tables to extract all customer info using T-SQL

i want to Write a query using the temporary date table to show rows for every customer for every month since the month they first purchased from us. The table should detail the customer ID, customer name, month, Date of first Purchase, Units Purchased that month, Value Purchased that month, Cumulative Units Purchased, Cumulative Value Purchased and the Days since last purchase and the last day of the month.
i've tried this code
select c.Id AS CustomerId
,c.FirstName+' '+c.LastName as CustomerName
,DATENAME(MM,d.OrderDate) AS MonthofFirstPurchase
--,sum(d.TotalAmount) AS CummulativeValue
,d.OrderDate AS DateOfFirstPurchase
,Datediff(dd,o.OrderDate,getdate()) as DateSinceLastPurchase
from[dbo].[Customer]c inner join [dbo].[Order] b on b.CustomerId = c.Id
join (select max(Id) as OrderId, min(Id) as minOrder,[CustomerId] from [dbo].[Order] group by [CustomerId])conn on c.Id = conn.[CustomerId]
join [dbo].[Order]o on o.[Id] = conn.OrderId
join [dbo].[Order]d on d.[Id] = conn.minOrder
--join [dbo].[OrderItem]b on = conn.OrderId
but i keep getting errors i am a beginner at this
Please note that I did not execute the query.
If you do not want that column please try the below query. I did not execute the query though
;WITH CTE_Temp
AS
(
SELECT max(Id) AS OrderId
, min(Id) AS minOrder
, [CustomerId]
FROM [dbo].[Order]
GROUP BY [CustomerId]
)
SELECT c.Id AS CustomerId
, c.FirstName + ' ' + c.LastName AS CustomerName
, DATENAME(MM, d.OrderDate) AS MonthofFirstPurchase
--,sum(d.TotalAmount) AS CummulativeValue
, d.OrderDate AS DateOfFirstPurchase
, Datediff(dd, o.OrderDate, getdate()) AS DateSinceLastPurchase
FROM [dbo].[Customer] c
INNER JOIN [dbo].[Order] b ON b.CustomerId = c.Id
INNER JOIN CTE_Temp conn ON c.Id = conn.[CustomerId]
INNER JOIN [dbo].[Order] o ON o.[Id] = conn.OrderId
INNER JOIN [dbo].[Order] d ON d.[Id] = conn.minOrder
If you need the sum(d.TotalAmount) AS CummulativeValue. Just try the query
;WITH CTE_Temp
AS
(
SELECT max(Id) AS OrderId
, min(Id) AS minOrder
, [CustomerId]
FROM [dbo].[Order]
GROUP BY [CustomerId]
),
CTE_TEMP1
AS
(
SELECT CTE_Temp.[CustomerId], sum(d.TotalAmount) TotalAmount AS CummulativeValue
FROM [dbo].[Order] d INNER JOIN CTE_Temp ON d.[Id] = CTE_Temp.minOrder
GROUP BY CTE_TEMP.[CustomerId]
)
SELECT c.Id AS CustomerId
, c.FirstName + ' ' + c.LastName AS CustomerName
, DATENAME(MM, d.OrderDate) AS MonthofFirstPurchase
,CTE_TEMP1.TotalAmount AS CummulativeValue
, d.OrderDate AS DateOfFirstPurchase
, Datediff(dd, o.OrderDate, getdate()) AS DateSinceLastPurchase
FROM [dbo].[Customer] c
INNER JOIN [dbo].[Order] b ON b.CustomerId = c.Id
INNER JOIN CTE_Temp conn ON c.Id = conn.[CustomerId]
INNER JOIN [dbo].[Order] o ON o.[Id] = conn.OrderId
INNER JOIN CTE_TEMP1 d ON d.CustomerId = c.id
I have modified the anser provided by Gopakumar and i came to the solution of the problem. The code below works perfectly well for its purpose
;WITH CTE_Temp
AS
(
SELECT max(Id) AS MaxOrder
, min(Id) AS MinOrder
, [CustomerId]
FROM [dbo].[Order]
GROUP BY [CustomerId]
),
CTE_TEMP1 AS(SELECT CTE_TEMP.CustomerId,sum([UnitQuantity]) AS UnitsPurchasedForMonth,sum(TotalAmount) AS ValueForMonth
from [dbo].[OrderItem]p left outer join [dbo].[Order] e on p.Id = e.Id
INNER JOIN CTE_Temp ON e.[Id] = CTE_Temp.minOrder GROUP BY CTE_TEMP.CustomerId),
CTE_TEMP2 AS(SELECT e.CustomerId,sum([UnitQuantity]) AS CummulativeUnitsPurchased,sum(TotalAmount) AS CummulativeValue
from [dbo].[OrderItem]p inner join [dbo].[Order] e on p.Id = e.Id group by e.CustomerId)
SELECT c.Id AS CustomerId
, c.FirstName + ' ' + c.LastName AS CustomerName
, DATENAME(MM, o.OrderDate) AS MonthofFirstPurchase
, o.OrderDate AS DateOfFirstPurchase
,d.ValueForMonth AS ValuePurchasedForMonth
,d.UnitsPurchasedForMonth
,e.CummulativeUnitsPurchased
,e.CummulativeValue
, Datediff(dd, a.OrderDate, getdate()) AS DateSinceLastPurchase
,EOMONTH(o.OrderDate) AS LastDayOfMonth
FROM [dbo].[Customer] c
INNER JOIN CTE_Temp conn ON c.Id = conn.CustomerId
INNER JOIN [dbo].[Order] o ON o.[Id] = conn.MinOrder
INNER JOIN CTE_TEMP1 d ON d.CustomerId = c.id
INNER JOIN [dbo].[Order] a on a.Id = conn.MaxOrder
inner join CTE_TEMP2 e on c.Id = e.CustomerId
you can edit as you like to get your results

alternative to sub query in join

I have a SQL query that I'm trying to optimize.
Is there a better way to avoid using subquery here?
Got a suggestion on using Row_number(),
posting this with some corrections
DECLARE #curdate DATETIME
SET #curdate = GETDATE()
SELECT DISTINCT
SIS.StudentID, StudentCoverage.StudentCoverageDataID,
Student.FirstName, Student.LastName,
Student.DateOfBirth, Student.Gender,
ASMT.AssessmentDate
FROM
SIS (NOLOCK)
INNER JOIN
SISMaster (NOLOCK) ON SISMaster.SISID = SIS.SISID
INNER JOIN
Assessment ASMT ON SIS.StudentID = ASMT.StudentId
INNER JOIN
StudentCoverage (NOLOCK) ON StudentCoverage.StudentID = SIS.StudentID
INNER JOIN
Organization (NOLOCK) ON StudentCoverage.OrgID = Organization.OrganizationID
INNER JOIN
Student (NOLOCK) ON Student.StudentID = SIS.StudentID
INNER JOIN
StudentCoverageData (NOLOCK) ON StudentCoverageData.StudentCoverageID = StudentCoverage.StudentCoverageID
AND StudentCoverageData.StudentCoverageDataID = (SELECT TOP 1 StudentCoverageData.StudentCoverageDataID
FROM StudentCoverage
INNER JOIN StudentCoverageData ON StudentCoverageData.StudentCoverageID = StudentCoverage.StudentCoverageID
WHERE StudentCoverage.StudentId = SIS.StudentID
AND StudentCoverageData.Active = 1
AND StudentCoverageData.EffectiveDate <= #curdate
AND (StudentCoverageData.ExitDate IS NULL OR StudentCoverageData.ExitDate > #curdate)
ORDER BY StudentCoverageData.AsOfDate DESC)
All Tables in your subquery is exists in inner join clause, so you could rewrite your query like this:
;WITH temps AS
(
DECLARE #curdate DATETIME = GETDATE()
SELECT
SIS.StudentID, StudentCoverage.StudentCoverageDataID,
Student.FirstName, Student.LastName,
Student.DateOfBirth, Student.Gender,
ASMT.AssessmentDate,
ROW_NUMBER() OVER (PARTITION BY StudentCoverageData.StudentCoverageDataID ORDER BY StudentCoverageData.AsOfDate) AS RowIndex
FROM
SIS (NOLOCK)
INNER JOIN
SISMaster (NOLOCK) ON SISMaster.SISID = SIS.SISID
INNER JOIN
StudentCoverage (NOLOCK) ON StudentCoverage.StudentID = SIS.StudentID
INNER JOIN
Organization (NOLOCK) ON StudentCoverage.OrgID = Organization.OrganizationID
INNER JOIN
Student (NOLOCK) ON Student.StudentID = SIS.StudentID
INNER JOIN
StudentCoverageData (NOLOCK) ON StudentCoverageData.StudentCoverageID = StudentCoverage.StudentCoverageID
WHERE StudentCoverageData.Active = 1
AND StudentCoverageData.EffectiveDate <= #curdate
AND (StudentCoverageData.ExitDate IS NULL OR StudentCoverageData.ExitDate > #curdate)
)
SELECT * FROM temps t
WHERE t.RowIndex = 1

sql server 2008, how to get rid of duplications when inner join 3 tables

here's my query. when I inner join 2 tables, there's no problem.
SELECT S.* ,
U.Avatar ,
U.Displayname ,
ROW_NUMBER() OVER ( ORDER BY S.Id DESC ) rownum
FROM dbo.Smoothie AS S
INNER JOIN dbo.[User] AS U ON S.UserId = U.Id
WHERE S.IsPublic = 1
AND S.Status = 3
AND S.UserId = 2
then, I added another inner join. now, I got alot duplications.
SELECT S.* ,
U.Avatar ,
U.Displayname,
ROW_NUMBER() OVER ( ORDER BY S.Id DESC ) rownum
FROM dbo.Smoothie AS S
INNER JOIN dbo.[User] AS U ON S.UserId = U.Id
INNER JOIN dbo.Favorite AS F ON U.Id = F.UserId
WHERE S.IsPublic = 1
AND S.Status = 3
AND F.UserId = 2
one solutions is to use distinct. however, I have to comment out row_number, i need that row_number to do paging. is there another way to get rid of duplication?
SELECT DISTINCT S.* ,
U.Avatar ,
U.Displayname
-- ROW_NUMBER() OVER ( ORDER BY S.Id DESC ) rownum
FROM dbo.Smoothie AS S
INNER JOIN dbo.[User] AS U ON S.UserId = U.Id
INNER JOIN dbo.Favorite AS F ON U.Id = F.UserId
WHERE S.IsPublic = 1
AND S.Status = 3
AND F.UserId = 2
Why not use the query you have, without the row_number as a subquery, then add the row number back later:
SELECT *,
ROW_NUMBER() OVER ( ORDER BY subQuery.Id DESC ) rownum
FROM (
SELECT DISTINCT S.* ,
U.Avatar ,
U.Displayname
FROM dbo.Smoothie AS S
INNER JOIN dbo.[User] AS U ON S.UserId = U.Id
INNER JOIN dbo.Favorite AS F ON U.Id = F.UserId
WHERE S.IsPublic = 1
AND S.Status = 3
AND F.UserId = 2
) AS subQuery
Dense_Rank would also do the job with the your otherwise unmodified query.

Resources