Two If selection while a select query - sql

SELECT o.id, o.id as oid, o.id as orderId, o.cid, o.date, o.state,
o.price, o.currency, o.lastChange, o.url AS permalink, o.period,
o.bloggerId, o.bloggerShare, o.offerValidity, o.rebate, o.cid,
o.reason, o.bidReason, o.bidDate, o.bidPeriod, o.rate,
o.lastChange2, o.permalinkDate, o.cancelDate, o.bidValidDate,
o.acceptDate, o.approveDate, o.archived, o.bloggerPrice,
o.customerPrice, o.cancelReason, o.listPrice, o.adFormat,
o.lastPayDate, o.startDate, o.endDate, o.customerBidDate,
o.zoneId, c.campaignStartDate, c.campaignEndDate,
c.type as campaignType, c.test, c.test1, c.special, c.packageId,
c.fixPrice, c.type, c.priceBidding, c.textCreation, o.hiddenField,
o.startDate, p.url as producturlold, p.pressurl, p.companyurl,
p.blogurl, p.mediaurl, p.short,
p.description as productDescription, p.description2, p.image,
c.teaser, c.kind, c.title, mc.country as campaignCountry,
c.minlen, c.productPrice, c.currency as campaignCurrency,
c.productTitle, c.url, c.producturl, c.pressurl, c.companyurl,
c.blogurl, c.mediaurl, c.description, c.image, c.teaser,
c.productReturn, c.testProduct, c.mid as customerId, c.adText,
c.fixAdText, c.requiresBlog, c.bidStop, c.accountingPeriod,
c.actionCodeType, c.actionCodesDescription, ac.code,
ac2.code as massCode, b.title as blogtitle, b.url as bloggerurl,
b.pis as pis, b.uniqueVisitors as uvs, b.pisCounter as pisCounter,
b.uvsCounter as uvsCounter, b.aPI as aPI, b.aUV as aUV,
b.id as blogId, p.title as productTitleOld,
b.lastChange as blogLastChange, b.trRank, r1.rate as orderRate,
r2.Rate as memberRate, b.reviews
FROM rates r1, rates r2, orders o
left join blog b on (o.blogId = b.id)
left join codes ac on (ac.orderId = o.id), campaign c
left join product p on (c.productId = p.id)
left join codes ac2 on (ac2.campaignId = c.id and
c.actionCodeType = 2),
person mc
where o.cid = c.id
and mc.mid = c.mid
and o.id = '223704'
and o.state <> 0
and r1.currency = o.currency
and r2.currency = 'EUR'
and r1.date = FROM_UNIXTIME(o.date, '%Y-%m-%d')
and r2.date = r1.date
I wnat to test if memberRate and orderRate is Null it should continue how can i do that? Any idea?

Tack this on the end should do the trick:
--Within the WHERE clause
AND r2.Rate IS NOT NULL
AND r1.Rate IS NOT NULL

I'm not sure I understand what you are asking, but add and memberRate is not null and orderRate is not null to the end of your query and you will skip all results where either of those two fields are null.

Related

JOIN two SELECT without UNION

It needs to download the ID, name and surname of those who have registered by the deadline and have an identity card (with the relevant conditions) or passport (with the relevant conditions). ID card and passport are two separate tables.
I have made the SQL queries in UNION format and it works:
select distinct p.id, p.name, p.surname from persons.person p
join persons.documents d on d.person_id = p.id
join persons.id_card idd on d.id_card_id = idd.id
join persons.id_card_to_registration ir on idd.id = ir.id_card
join registrations.registration r on ir.registration_id = r.id
where p.created_at >= '2022-01-01'
and p.created_at <= '2022-03-30'
and p.registration_id = r.id
and ir.status in (0,5)
UNION
select distinct p.id, p.name, p.surname from persons.person p
join persons.documents d on d.person_id = p.id
join persons.passport pass on d.passport_id = pass.id
join persons.passport_country pc on pc.id = pass_country_id
join persons.passport_to_registration pr on pass.id = pr.passport_id
join registrations.registration r on pr.registration_id = r.id
where p.created_at >= '2022-01-01'
and p.created_at <= '2022-03-30'
and p.registration_id = r.id
and pc.zone in (0,1) or (pc.zone is null and pass.safe = true);
I would now like to do this SQL in one query without union and unfortunately it doesn't work for me - I tried to do it like this:
select distinct p.id, p.name, p.surname from persons.person p
join persons.documents d on d.person_id = p.id
left join persons.id_card idd on d.id_card_id = idd.id
left join persons.id_card_to_registration ir on idd.id = ir.id_card
left join persons.passport pass on d.passport_id = pass.id
left join persons.passport_country pc on pc.id = pass_country_id
left join persons.passport_to_registration pr on pass.id = pr.passport_id
join registrations.registration r on ir.registration_id = r.id
where p.created_at >= '2022-01-01'
and p.created_at <= '2022-03-30'
and p.registration_id = r.id
and (ir.status in (0,5) or ir.status is null)
and pc.zone in (0,1) or (pc.zone is null and pass.safe = true)
And it doesn't return any records to me. I would like some advice on what error I have made. And is it possible to create such a query without union?
The SQL in clause may help to filter by each condition. This may be the way to avoid the union clause, please let me know if this works for you:
select distinct p.id, p.name, p.surname from persons.person p
where p.created_at >= '2022-01-01'
and p.created_at <= '2022-03-30'
and ((p.id in
(select distinct p2.id from persons.person p2
d.person_id from persons.documents d on d.person_id = p2.id
join persons.id_card idd on d.id_card_id = idd.id
join persons.id_card_to_registration ir on idd.id = ir.id_card
join registrations.registration r on ir.registration_id = r.id
where p2.registration_id = r.id
and ir.status in (0,5)
)
) or (
(p.id in
(select distinct p3.id from persons.person p3
d.person_id from persons.documents d on d.person_id = p3.id
join persons.passport pass on d.passport_id = pass.id
join persons.passport_country pc on pc.id = pass_country_id
join persons.passport_to_registration pr on pass.id = pr.passport_id
join registrations.registration r on pr.registration_id = r.id
where p3.registration_id = r.id
and pc.zone in (0,1) or (pc.zone is null and pass.safe = true);
)
)
))
I think you'll have better performance if you can convert the query to use EXISTS.
SELECT DISTINCT p.id, p.name, p.surname
FROM persons.person p
WHERE p.created_at >= '2022-01-01'
AND p.created_at <= '2022-03-30'
AND(EXISTS (SELECT *
FROM persons.documents d
JOIN persons.id_card idd
ON d.id_card_id = idd.id
JOIN persons.id_card_to_registration ir
ON idd.id = ir.id_card
JOIN registrations.registration r
ON ir.registration_id = r.id
WHERE p.id = d.person_id
AND p.registration_id = r.id
AND ir.status IN (0,5))
OR EXISTS (SELECT *
FROM persons.documents d
JOIN persons.passport pass
ON d.passport_id = pass.id
JOIN persons.passport_country pc
ON pc.id = pass_country_id
JOIN persons.passport_to_registration pr
ON pass.id = pr.passport_id
JOIN registrations.registration r
ON pr.registration_id = r.id
WHERE p.id = d.person_id
AND p.registration_id = r.id
AND pc.zone IN (0,1)
OR (pc.zone IS NULL
AND pass.safe = TRUE)))

Aggregating two rows, SQL

This is an example of what I'm working on
table
Forgive the picture, I couldn't figure out the table feature
This is my code
select o.id order_id, m.id, m.override_pay_amt
from orders o
left join movement_order mo
on o.id = mo.order_id
and mo.company_id = 'TMS'
left join movement m
on mo.movement_id = m.id
and m.company_id ='TMS'
where o.status != 'V' and o.company_id = 'TMS' and (o.id = '6008227' or o.id = '6000006')
order by o.id
I can't figure out how to combine order_id 6008227 in to one row.
I've tried:
select o.id order_id, m.id, sum(m.override_pay_amt) pay
from orders o
left join movement_order mo
on o.id = mo.order_id
and mo.company_id = 'TMS'
left join movement m
on mo.movement_id = m.id
and m.company_id ='TMS'
where o.status != 'V' and o.company_id = 'TMS' and (o.id = '6008227' or o.id = '6000006')
group by o.id
order by o.id
but when I do this, it makes me group by m.id and nothing changes in the table.
What am I missing?

Execute a query foreach row from a result set.

I have a query that needs to be executed for each row in a result set. I understand that I need to do this with cursors, but I dont know how.
The first query contains customers with a specific condition, I need to retreive the Id:s from them.
The second query selects the latest activity from these customers.
Query 1
SELECT DISTINCT c.Name, c.Id
FROM Persons p
JOIN Customers c ON c.id = p.Customer_Id
WHERE C.State = 3 AND c.SalesPerson_Id ='A3160011-CAA6-E411-A83E-AC7BA1B90A6D' AND c.Id NOT IN
(
SELECT Distinct p.Customer_Id
FROM Activities a
JOIN Persons p
ON a.Person_Id = p.Id
WHERE a.[Type] IN (5,6) AND a.[Time] > getdate()-30 AND a.[Time] < getdate()
)
AND c.id NOT IN
(
SELECT
DISTINCT p.Customer_Id
FROM
Persons p
JOIN HtmlEmails he ON p.Id = he.UserId
JOIN ReportLog rl ON he.Id = rl.HtmlEmails_Id
WHERE rl.[Time] > getdate()-30 AND rl.[Time] < getdate())
Query 2
SELECT TOP 1 *
FROM(
SELECT TOP 1 c.Name AS 'CustomerName', c.Id AS 'CustomerId', a.[Time] AS 'LastActivity',(p.FirstName + ' ' + p.LastName) AS 'UserFullName' , 'Login' AS 'Type'
FROM Activities a
JOIN Persons p ON p.Id = a.Person_Id
JOIN Customers c ON p.Customer_Id = c.Id
WHERE a.[Type] IN (5,6) AND a.[Time] < getdate()-30
ORDER BY a.[Time] DESC
UNION
SELECT TOP 1 c.Name AS 'CustomerName', c.Id AS 'CustomerId', a.[Time] AS 'LastActivity',(p.FirstName + ' ' + p.LastName) AS 'UserFullName' , 'Email' AS 'Type'
FROM Activities a
JOIN HtmlEmails he ON a.TargetId = he.Id
JOIN ReportLog rl on he.Id = rl.HtmlEmails_Id
JOIN Persons p ON p.Id = a.Person_Id
JOIN Customers c ON p.Customer_Id = c.Id
WHERE a.[Time] < getdate()-30
ORDER BY a.[Time] DESC
)AS x
ORDER BY 'LastActivity' DESC
Thanks!

Calculating stock quantity from multiple table transactions with SQL

We had an issue with our stock whereby we had a balance column that would be added to or subtracted from whenever a transaction occurred.
There were some issues that we could not trace and hence have made changes whereby the stock would be calculated by adding and subtracting (where appropriate) the quantity moving and come up to today's stock value.
However now, the structure is such that one product has multiple stocks therefore product A with expiry 01/2012, 02/2013 etc.
I have currently created a query whereby for one stock of a product, it would calculate its current stock as follows:
select
(select ISNULL(sum(gd.qty),0) as grnadd from grns as g
INNER JOIN grndetails as gd ON g.id = gd.grnid
INNER JOIN stocks as s ON s.id = gd.stockid
where g.locationid = 10 and s.prodid =2653)
-
(select ISNULL(sum(cod.qty), 0) as salesub from salesorders as co
INNER JOIN salesorddetails as cod ON co.id = cod.cusordid
INNER JOIN stocks as s ON s.id = cod.stockid
where co.status != 'cancel' and co.locid = 10 and s.prodid =2653)
-
(select ISNULL(sum(cod.qty), 0) as cussub from customerorders as co
INNER JOIN customerorddetails as cod ON co.id = cod.cusordid
INNER JOIN stocks as s ON s.id = cod.stockid
where co.status != 'cancel' and co.locid = 10 and s.prodid =2653)
Therefore in this case the stock is calculated for one product however can I make a query that would list all products with their totals (as above) in the second column?
Thank you and hope the structure is understood from the above query
EDIT:
Stocks Table: id, prodid, expiry
Products Table: id, tradename
GRN Details Table: id, grnid, qty, stockid (since its affecting the stock not product)
Sales & Customer Order Details Table: id, cusordid, qty, stockid
GRN & Sales & Cus Ord Table: id, locid
Locations Table: id, locname
try to include all product-ids and group by it. here's some proposed code
select prodid, sum(total) as total from (
(select s.prodid
, ISNULL(sum(gd.qty),0) as total
from grns as g
INNER JOIN grndetails as gd
ON g.id = gd.grnid
INNER JOIN stocks as s
ON s.id = gd.stockid
where g.locationid = 10 group by s.prodid)
union all
(select s.prodid
, ISNULL(sum(cod.qty), 0)*(-1) as total
from salesorders as co
INNER JOIN salesorddetails as cod
ON co.id = cod.cusordid
INNER JOIN stocks as s
ON s.id = cod.stockid
where co.status != 'cancel'
and co.locid = 10 group by s.prodid)
union all
(select s.prod_id
, ISNULL(sum(cod.qty), 0)*(-1) as total
from customerorders as co
INNER JOIN customerorddetails as cod
ON co.id = cod.cusordid
INNER JOIN stocks as s
ON s.id = cod.stockid
where co.status != 'cancel'
and co.locid = 10 group by s.prodid)
) as x
group by prodid
i have changed all the minuses to union-alls so that the product-ids will not get subtracted from each other and the grand total will be calculated respective to your product-ids.
Try this:
WITH
S AS (
SELECT DISTINCT prodid FROM stocks
),
L AS (
/* SELECT 10 AS locationid */
SELECT DISTINCT locationid FROM grns
),
T1 AS (
select
g.locationid,
s.prodid,
sum(gd.qty) as grnadd
from grns as g
INNER JOIN grndetails as gd ON g.id = gd.grnid
INNER JOIN stocks as s ON s.id = gd.stockid
GROUP BY g.locationid, s.prodid
),
T2 AS (
select
co.locid as locationid,
s.prodid,
sum(cod.qty) as salesub
from salesorders as co
INNER JOIN salesorddetails as cod ON co.id = cod.cusordid
INNER JOIN stocks as s ON s.id = cod.stockid
where co.status != 'cancel'
GROUP BY co.locid, s.prodid
),
T3 AS (
select
co.locid as locationid,
s.prodid,
sum(cod.qty) as cussub
from customerorders as co
INNER JOIN customerorddetails as cod ON co.id = cod.cusordid
INNER JOIN stocks as s ON s.id = cod.stockid
where co.status != 'cancel'
GROUP BY co.locid, s.prodid
)
SELECT
S.prodid, L.locationid, ISNULL(grnadd, 0) - ISNULL(salesub, 0) - ISNULL(cussub, 0)
FROM
S CROSS JOIN
L LEFT OUTER JOIN
T1 ON T1.locationid = L.locationid AND T1.prodid = S.prodid LEFT OUTER JOIN
T2 ON T2.locationid = L.locationid AND T2.prodid = S.prodid LEFT OUTER JOIN
T3 ON T3.locationid = L.locationid AND T3.prodid = S.prodid
I assumed that location might be also important, so it returns 3 columns. If you want results only for location with id 10, then in L CTL uncomment first line and comment second.
assuming lots about your data model (hopefully i understood the question right), a group by might be the answer:
select
(select s.prodid, ISNULL(sum(gd.qty),0) as grnadd from grns as g
INNER JOIN grndetails as gd ON g.id = gd.grnid
INNER JOIN stocks as s ON s.id = gd.stockid
where g.locationid = 10
GROUP BY s.prodid)
-
(select s.prodid, ISNULL(sum(cod.qty), 0) as salesub from salesorders as co
INNER JOIN salesorddetails as cod ON co.id = cod.cusordid
INNER JOIN stocks as s ON s.id = cod.stockid
where co.status != 'cancel' and co.locid = 10
GROUP BY s.prodid)
-
(select s.prodid, ISNULL(sum(cod.qty), 0) as cussub from customerorders as co
INNER JOIN customerorddetails as cod ON co.id = cod.cusordid
INNER JOIN stocks as s ON s.id = cod.stockid
where co.status != 'cancel' and co.locid = 10
GROUP BY s.prodid)

can i pivot this entire query to return different results?

This query is returning exactly what i need but im trying to create a pivot table out of it as well. I want to be able to SUM the column defined as SLAStatus in the CASE clause (dont know if thats even possible) as well as count the OrderID column as well as calculate(sum of SLAStatus column)/(Count of OrderID Column) to return a percentage of orders withing SLA. Been looking online everywhere but cant seem to figure this out
SELECT oi.OrderID, o.Address1 as StreetAddress, c.Name as County, o.State, p.Abbreviation, oi.OrderDate as Dateentered,
DATEADD(dd, DATEDIFF(dd, 0, oi.DeliveredDate), 0) as DateCompleted, DATEADD(dd, DATEDIFF(dd, 0, oi.RequiredByDate), 0) as EstimatedDeliveryDate,
CASE
WHEN oi.DeliveredDate <= oi.RequiredByDate THEN '1'
ELSE '0'
END AS SLAStatus,
cl.Name as Client, clb.Name as Client2, v.ContactFirstName + ' ' + v.ContactLastName as Appraiser
FROM OrderItems oi
JOIN Orders o on o.OrderID = oi.OrderID
JOIN Counties c on c.FIPS = o.FIPS
JOIN Products p on p.ProductID = oi.ProductID
JOIN Clients cl on cl.ClientID = o.ClientID
JOIN ClientBranches clb on clb.ClientID = cl.ClientID
JOIN Vendors v on v.VendorID = oi.VendorID
JOIN Milestones m on m.MilestoneID = oi.LastMilestoneID
WHERE cl.Name not like '%TEST%'
and '2012-03-01' <=
(select MAX(MilestoneDate)
from OrderItemMilestones
where OrderID = oi.OrderID
and OrderItemID = oi.OrderItemID
and MilestoneID in (100,130,140,150))
and '2012-04-10' >=
(select MAX(MilestoneDate)
from OrderItemMilestones
where OrderID = oi.OrderID
and OrderItemID = oi.OrderItemID
and MilestoneID in (100,130,140,150))
I would recommend using a common table expression (CTE). Just wrap your original query in a CTE then you can do the grouping you are looking for.
with originalCTE as
(
SELECT oi.OrderID, o.Address1 as StreetAddress, c.Name as County, o.State,
p.Abbreviation, oi.OrderDate as Dateentered,
DATEADD(dd, DATEDIFF(dd, 0, oi.DeliveredDate), 0) as DateCompleted, DATEADD(dd,
DATEDIFF(dd, 0, oi.RequiredByDate), 0) as EstimatedDeliveryDate,
CASE
WHEN oi.DeliveredDate <= oi.RequiredByDate THEN '1'
ELSE '0'
END AS SLAStatus,
cl.Name as Client, clb.Name as Client2, v.ContactFirstName + ' ' + v.ContactLastName as Appraiser
FROM OrderItems oi
JOIN Orders o on o.OrderID = oi.OrderID
JOIN Counties c on c.FIPS = o.FIPS
JOIN Products p on p.ProductID = oi.ProductID
JOIN Clients cl on cl.ClientID = o.ClientID
JOIN ClientBranches clb on clb.ClientID = cl.ClientID
JOIN Vendors v on v.VendorID = oi.VendorID
JOIN Milestones m on m.MilestoneID = oi.LastMilestoneID
WHERE cl.Name not like '%TEST%'
and '2012-03-01' <=
(select MAX(MilestoneDate)
from OrderItemMilestones
where OrderID = oi.OrderID
and OrderItemID = oi.OrderItemID
and MilestoneID in (100,130,140,150))
and '2012-04-10' >=
(select MAX(MilestoneDate)
from OrderItemMilestones
where OrderID = oi.OrderID
and OrderItemID = oi.OrderItemID
and MilestoneID in (100,130,140,150))
)
select sum(SLAStatus), sum(SLAStatus) / count(orderID)
from originalCTE;
If I understand correctly what you are looking for, then that is how I would do it. Hope this helps.