Add condition to two sub selects in query - database

I have this query.
SELECT DISTINCT
u.email,
(
SELECT
count(DISTINCT o.id)
FROM
orders o
INNER JOIN cart_dates cd ON cd.order_id = o.id
WHERE
u.id = o.user_id
) as total,
(
SELECT
count(DISTINCT o.id)
FROM
orders o
INNER JOIN cart_dates cd ON cd.order_id = o.id AND o.pre_order = TRUE
WHERE
u.id = o.user_id
) as count
FROM
users u
How can I get rows where for example, count > (total / 2)?

I am only assumming to answer this question.
SELECT
u.email
FROM
users u
INNER JOIN cart_dates cd ON cd.order_id = o.id
GROUP BY
u.email
HAVING
COUNT(DISTINCT Case when o.pre_order = TRUE then o.id else null end) >
(COUNT(DISTINCT o.id)/2)
I tried to making it more simpler.

Related

Add condition to sub select in query

I have this query
SELECT DISTINCT
u.email,
(
SELECT
count(DISTINCT o.id)
FROM
orders o
INNER JOIN cart_dates cd ON cd.order_id = o.id
WHERE
u.id = o.user_id
) as count
FROM
users u
How can I get rows only when count is, for example, < 20?
you can use group by and having clause.
select u.email
from users u
inner join orders o on o.user_Id = u.id
inner join card_dates cd on cd.order_id = o.id
group by u.email
having count(distinct o.id) < 20

SQL query to fetch repeat column values within time frame

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

Get Max(id) from one to many table

I know this question was asked many times but I was tring and trying without success
I have one to many relationship between two tables and some more inner-joins to get more data.
Here is my query:
SELECT
ShopOffer.OfferID,
ShopOffer.OfferMessage,
Shop.ID,
Shop.Name,
Shop.Phone,
[User].Name,
[User].UserID,
ShopOfferStatus.Name AS StatusName,
BlockedShopInUser.IsBlocked
FROM
ShopOffer
INNER JOIN ShopOfferStatus ON ShopOffer.ShopOfferStatusID = ShopOfferStatus.ShopOfferStatusID
INNER JOIN Shop ON ShopOffer.ShopID = Shop.ShopID
INNER JOIN UserRequest ON ShopOffer.UserRequestID = UserRequest.UserRequestID
INNER JOIN [User] ON UserRequest.UserID = [User].UserID
INNER JOIN BlockedShopInUser ON Shop.ShopID = BlockedShopInUser.ShopID AND [User].UserID = BlockedShopInUser.UserID
Each shop can create many offers. In that query I would like to get only the last offer for each shop.
Thanks.
Here is a way:
;WITH LastShopOffer AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY ShopID ORDER BY OfferID DESC)
FROM ShopOffer
)
SELECT
SO.OfferID,
SO.OfferMessage,
S.ID,
S.Name,
S.Phone,
U.Name,
U.UserID,
SOS.Name AS StatusName,
B.IsBlocked
FROM ( SELECT *
FROM LastShopOffer
WHERE RN = 1) SO
INNER JOIN ShopOfferStatus SOS
ON SO.ShopOfferStatusID = SOS.ShopOfferStatusID
INNER JOIN Shop S
ON SO.ShopID = S.ShopID
INNER JOIN UserRequest UR
ON SO.UserRequestID = UR.UserRequestID
INNER JOIN [User] U
ON UR.UserID = U.UserID
INNER JOIN BlockedShopInUser B
ON S.ShopID = B.ShopID
AND U.UserID = B.UserID;
I think you have to start with Shop and then perform a CROSS APPLY on the TOP 1 record from ShopOffer:
SELECT
ShopOffer.OfferID,
ShopOffer.OfferMessage,
Shop.ID,
Shop.Name,
Shop.Phone,
[User].Name,
[User].UserID,
ShopOfferStatus.Name AS StatusName,
BlockedShopInUser.IsBlocked
FROM Shop
CROSS APPLY (
SELECT TOP 1 OfferID, OfferMessage, ShopOfferStatusID, UserRequestID
FROM ShopOffer AS s
WHERE s.ShopID = Shop.ShopID
ORDER BY s.OfferID DESC
) ShopOffer
INNER JOIN ShopOfferStatus ON ShopOffer.ShopOfferStatusID = ShopOfferStatus.ShopOfferStatusID
INNER JOIN UserRequest ON ShopOffer.UserRequestID = UserRequest.UserRequestID
INNER JOIN [User] ON UserRequest.UserID = [User].UserID
INNER JOIN BlockedShopInUser ON Shop.ShopID = BlockedShopInUser.ShopID AND [User].UserID = BlockedShopInUser.UserID

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.

multiple count in a sql query

i need a report from a database where i need the final result like
Number of Male, Number of Female, showing against city and finally against State.
I started off with something like.
SELECT p.StateName, d.CityName,
count(api.Gender) as Gender
FROM dbo.Application_Personal_information as api INNER JOIN
dbo.state as p ON api.State = p.ID INNER JOIN
dbo.City as d ON api.City= d.ID
group by p.StateName, d.CityName
when i do this
SELECT p.StateName, d.CityName,
count(api.Gender = 'Male) as Male,
count(api.Gender = 'Female) as Female,
FROM dbo.Application_Personal_information as api INNER JOIN
dbo.state as p ON api.State = p.ID INNER JOIN
dbo.City as d ON api.City= d.ID
group by p.StateName, d.CityName
it give's me error.
incorrect syntax near =.
i also tried with select statement
COUNT(select api.Gender from api where api.Gender ='Male') as Male,
But it is also not working.
...
Any idea?
SELECT
p.StateName, d.CityName,
sum(case when Gender ='Male' then 1 else 0 end ) as Male_count,
sum(case when Gender ='Female' then 1 else 0 end ) as Female_count
FROM
dbo.Application_Personal_information as api INNER JOIN
dbo.state as p ON api.State = p.ID INNER JOIN
dbo.City as d ON api.City= d.ID
group by
p.StateName, d.CityName
You could try the PIVOT function if you are using SQL Server 2005 or later:
WITH CTE AS
( SELECT p.StateName,
d.CityName,
api.Gender
FROM dbo.Application_Personal_information as api
INNER JOIN dbo.state as p
ON api.State = p.ID
INNER JOIN dbo.City as d
ON api.City= d.ID
)
SELECT *
FROM CTE
PIVOT
( COUNT(Gender)
FOR Gender IN ([Male], [Female])
) pvt

Resources