Subquery value bigger than another subquery value - sql

I've got a query which returns 8 columns, 2 of them are sub queries which returns the maximum date. I would like to create 9th column which will return a number, asterisk or something to highlight the rows where date in column 1 is bigger than in column 2 but still keep all the rows. Is it possible somehow?
Edit:
this is the query
The columns I want to see the differences in are MaxExpDateGB and MaxExpDatePH
select
i.ITEM,
i.COMPANY,
count(distinct i.LOGISTICS_UNIT) as LocationsGB,
sum(on_hand_qty) as StockGB,
(select
Count(distinct location)
from
LOCATION_INVENTORY b where b.ITEM = i.ITEM and b.TEMPLATE_FIELD1 = '139' and b.TEMPLATE_FIELD4 is not null and b.TEMPLATE_FIELD5 is null) as LocationsPH,
(select
sum(on_hand_qty)
from
LOCATION_INVENTORY b where b.ITEM = i.ITEM and b.TEMPLATE_FIELD1 = '139' and b.TEMPLATE_FIELD4 is not null and b.TEMPLATE_FIELD5 is null) as StockPH,
MAX(i.Expiration_DATE) as MaxExpDateGB,
(select
MAX(a.Expiration_DATE)
from
LOCATION_INVENTORY a where a.ITEM = i.ITEM and a.TEMPLATE_FIELD1 = '139' and a.TEMPLATE_FIELD4 is not null and a.INVENTORY_STS = 'available' ) as MaxExpDatePH
from
LOCATION l inner join LOCATION_INVENTORY i on l.LOCATION = i.LOCATION inner join ITEM t on i.ITEM = t.ITEM
where
t.USER_DEF6 = '10'
and i.LOCATION = '000-gb-01'
group by
i.item,i.company

Without any refactoring
select *, case when LocationsPH > StockPH then '*' end flag
from (
select
i.ITEM,
i.COMPANY,
count(distinct i.LOGISTICS_UNIT) as LocationsGB,
sum(on_hand_qty) as StockGB,
(select
Count(distinct location)
from
LOCATION_INVENTORY b where b.ITEM = i.ITEM and b.TEMPLATE_FIELD1 = '139' and b.TEMPLATE_FIELD4 is not null and b.TEMPLATE_FIELD5 is null
) as LocationsPH,
(select
sum(on_hand_qty)
from
LOCATION_INVENTORY b where b.ITEM = i.ITEM and b.TEMPLATE_FIELD1 = '139' and b.TEMPLATE_FIELD4 is not null and b.TEMPLATE_FIELD5 is null
) as StockPH,
MAX(i.Expiration_DATE) as MaxExpDateGB,
(select
MAX(a.Expiration_DATE)
from
LOCATION_INVENTORY a where a.ITEM = i.ITEM and a.TEMPLATE_FIELD1 = '139' and a.TEMPLATE_FIELD4 is not null and a.INVENTORY_STS = 'available'
) as MaxExpDatePH
from
LOCATION l
inner join LOCATION_INVENTORY i on l.LOCATION = i.LOCATION inner join ITEM t on i.ITEM = t.ITEM
where
t.USER_DEF6 = '10'
and i.LOCATION = '000-gb-01'
group by
i.item,i.company
) t

Related

Pull a separate column that matches the (min) of an aggregate function

It works well so far but I am stumped from here as I am brand new to this. This query finds the closest distance match, pairing up every item in the "FAILED" folder against everything that isn't in the "FAILED" folder.
There is a column "RouteID" in the "table p" that I want to match up with the min() aggregate.
I cannot process how to make the SELECT query simply show the associated "RouteID" column from tbl p but ultimately, I want to turn this into an update query that will SET a.Route = p.Route that is associated with the min()
Any help would be appreciated.
SELECT a.name, a.Reference1,
MIN(round(ACOS(COS(RADIANS(90-a.lat))
*COS(RADIANS(90-p.latpoint))
+SIN(RADIANS(90-a.lat))
*SIN(RADIANS(90-p.latpoint))
*COS(RADIANS(a.lon-p.longpoint)))
*3958.756,2)) AS 'DISTANCE'
FROM tblOrder AS a WITH (NOLOCK)
LEFT JOIN
(
SELECT b.lat AS latpoint, b.lon AS longpoint,
b.Sequence, b.routeid
from tblOrder b WITH (NOLOCK)
WHERE b.CUSTID = 180016
AND b.routeID <> 'FAILED'
AND b.StopType = 1
) AS p ON 1=1
WHERE a.CustID = 180016
AND a.RouteID = 'FAILED'
AND a.StopType = 1
AND P.RouteID <> 'FAILED'
GROUP BY
a.name, a.Reference1
You can select them separately and then join them
SELECT c.name, c.Reference1, q.RouteID
FROM
(
SELECT a.name, a.Reference1,
MIN(round(ACOS(COS(RADIANS(90-a.lat))
*COS(RADIANS(90-p.latpoint))
+SIN(RADIANS(90-a.lat))
*SIN(RADIANS(90-p.latpoint))
*COS(RADIANS(a.lon-p.longpoint)))
*3958.756,2)) AS 'DISTANCE'
FROM tblOrder AS a WITH (NOLOCK)
LEFT JOIN
(
SELECT b.lat AS latpoint, b.lon AS longpoint,
b.Sequence, b.routeid
from tblOrder b WITH (NOLOCK)
WHERE b.CUSTID = 180016
AND b.routeID <> 'FAILED'
AND b.StopType = 1
) AS p ON 1=1
WHERE a.CustID = 180016
AND a.RouteID = 'FAILED'
AND a.StopType = 1
AND P.RouteID <> 'FAILED'
GROUP BY
a.name, a.Reference1
) c
LEFT JOIN
(
SELECT b.lat AS latpoint, b.lon AS longpoint,
b.Sequence, b.routeid
from tblOrderRouteStops b WITH (NOLOCK)
WHERE b.CUSTID = 180016
AND b.routeID <> 'FAILED'
AND b.StopType = 1
) AS q
ON q.routeID = c.DISTANCE

query won't work after pivot

I'm trying to develop a query and i got something like this
SELECT a.No,
a.Finish,
a.Shift,
a.McCode,
d.NAME,
b.ItemCode,
b.ItemName,
b.Qty,
b.LotNo,
b.Description,
CASE
WHEN b.Description LIKE '%not good%' THEN 'NG'
ELSE 'OK'
END AS OKNG,
c.ItemCode AS matcode,
c.LotNo AS matlot,
CASE
WHEN e.GroupName = 'CONTACT' THEN 'CONTACT'
ELSE 'Coil/Silver/Wire'
END AS GroupName,
( c.Qty / ( a.Qty + a.QtyNg ) ) * b.Qty AS materialused
FROM PPRDDLV a
LEFT JOIN ICMUTTRAN b
ON a.PrdNo = b.TranNo
AND a.No = b.TranId
LEFT JOIN ICMUTTRAN c
ON a.PrdNo = c.TranNo
AND a.Finish = c.DatePost
AND c.TranTypeID = 6
AND c.LotNo <> '0'
LEFT JOIN popr d
ON a.OprCode = d.Code
LEFT JOIN ICITEM e
ON c.ItemId = e.id
WHERE c.qty IS NOT NULL
AND b.ItemCode IS NOT NULL
I got around 49000 records in around 2 seconds, then I wan't to pivot a column that has 2 kind of value, so I turned it to something like this
SELECT no,
finish,
shift,
mccode,
NAME,
itemcode,
itemname,
qty,
lotno,
description,
okng,
matcode,
matlot
FROM (SELECT a.No,
a.Finish,
a.Shift,
a.McCode,
d.NAME,
b.ItemCode,
b.ItemName,
b.Qty,
b.LotNo,
b.Description,
CASE
WHEN b.Description LIKE '%not good%' THEN 'NG'
ELSE 'OK'
END AS OKNG,
c.ItemCode AS matcode,
c.LotNo AS matlot,
CASE
WHEN e.GroupName = 'CONTACT' THEN 'CONTACT'
ELSE 'Coil/Silver/Wire'
END AS GroupName,
( c.Qty / ( a.Qty + a.QtyNg ) ) * b.Qty AS materialused
FROM PPRDDLV a
LEFT JOIN ICMUTTRAN b
ON a.PrdNo = b.TranNo
AND a.No = b.TranId
LEFT JOIN ICMUTTRAN c
ON a.PrdNo = c.TranNo
AND a.Finish = c.DatePost
AND c.TranTypeID = 6
AND c.LotNo <> '0'
LEFT JOIN popr d
ON a.OprCode = d.Code
LEFT JOIN ICITEM e
ON c.ItemId = e.id
WHERE c.qty IS NOT NULL
AND b.ItemCode IS NOT NULL) AS a
PIVOT (Max(materialused)
FOR groupname IN ([CONTACT],
[Coil/Silver/Wire])) AS b
but the query won't complete even after 10 minutes, it won't even show a single records. beside that one, the first query before I used pivot, I put an order by a.no but when I executed it, the result only shows to record 105 but the query is still working and no more record was loaded.
can anyone help me find out what's going on?
thank you!
Here's the sample data collected from the inner query and the expected value after the query.
enter image description here
I realize that I selected "matcode" in the outer select while it shouldn't be there (still didn't work though, and note for the column "material used", I'll be using it later after the pivot is done)
Try using conditional aggregate instead of pivot.
SELECT no,
finish,
shift,
mccode,
NAME,
itemcode,
itemname,
qty,
lotno,
description,
okng,
matcode,
matlot,
[CONTACT] = Max(CASE WHEN GroupName = 'CONTACT' THEN materialused END),
[Coil/Silver/Wire] = Max(CASE WHEN GroupName <> 'CONTACT' THEN materialused END)
FROM (<inner query>) AS a
GROUP BY no,
finish,
shift,
mccode,
NAME,
itemcode,
itemname,
qty,
lotno,
description,
okng,
matcode,
matlot
---IF you don't have index on filter columns then try to apply for performance
SELECT a.No,
a.Finish,
a.Shift,
a.McCode,
d.NAME,
b.ItemCode,
b.ItemName,
b.Qty,
b.LotNo,
b.Description,
CASE WHEN b.Description LIKE '%not good%' THEN 'NG'
ELSE 'OK'
END AS OKNG,
c.ItemCode,
c.LotNo,
MAX(CASE WHEN e.groupname ='CONTACT' THEN ( c.Qty / ( a.Qty + a.QtyNg ) ) * b.Qty END)OVER(ORDER BY a.no) AS [CONTACT],
MAX(CASE WHEN e.groupname ='Coil/Silver/Wire' THEN ( c.Qty / ( a.Qty + a.QtyNg ) ) * b.Qty END)OVER(ORDER BY a.no) AS [Coil/Silver/Wire]
FROM PPRDDLV a WITH(NOLOCK)
LEFT JOIN ICMUTTRAN b WITH(NOLOCK)
ON a.PrdNo = b.TranNo
AND a.No = b.TranId
LEFT JOIN ICMUTTRAN c WITH(NOLOCK)
ON a.PrdNo = c.TranNo
AND a.Finish = c.DatePost
AND c.TranTypeID = 6
AND c.LotNo <> '0'
LEFT JOIN popr d WITH(NOLOCK)
ON a.OprCode = d.Code
LEFT JOIN ICITEM e
ON c.ItemId = e.id
WHERE c.qty IS NOT NULL
AND b.ItemCode IS NOT NULL

Using a group by to group a select statement

Using a group by to group a select stament
SELECT
k.Ivalue, k.JOBDESCRIPTION ,
count( k.Ivalue) as TOTAL
FROM
(SELECT
a."ID" as Ivalue, b."JOBDESCRIPTION", rq."CURRENTSTATUS"
FROM
tblG2o_Requests a
INNER JOIN
tblG2o_JOBS b ON a."JOBPOSTID" = b."ID"
INNER JOIN
(SELECT
r.REQUESTID, ir."CURRENTSTATUS"
FROM
TBLG2O_RESULTSPOOL r
INNER JOIN
tblG2o_Requests ir ON r.RequestID = ir."ID"
WHERE
r.ShortListed = '1') rq ON rq.REQUESTID = a."ID"
WHERE
"ACTIVE" = '1'
AND "DATECOMPLETED" IS NULL
ORDER BY
"REQUESTDATE" DESC) k
GROUP BY
k.JOBDESCRIPTION
What is the question? You seem to be missing the group by clause, and you do not need double quotes around field names unless you have spaces in them, and even then, if TSQL for example, you would use [] in preference.
I had to remove an ORDER BY in the subquery, that isn't allowed unless other conditions demand it (like TOP n in TSQL)
SELECT
k.Ivalue
, k.JOBDESCRIPTION
, COUNT(k.Ivalue) AS TOTAL
FROM (
SELECT
a.ID AS Ivalue
, b.JOBDESCRIPTION
, rq.CURRENTSTATUS
FROM tblG2o_Requests a
INNER JOIN tblG2o_JOBS b
ON a.JOBPOSTID = b.ID
INNER JOIN (
SELECT
r.REQUESTID
, ir.CURRENTSTATUS
FROM TBLG2O_RESULTSPOOL r
INNER JOIN tblG2o_Requests ir
ON r.RequestID = ir.ID
WHERE r.ShortListed = '1'
) rqenter
ON rq.REQUESTID = a.ID
WHERE ACTIVE = '1'
AND DATECOMPLETED IS NULL
) k
GROUP BY
k.Ivalue
, k.JOBDESCRIPTION
Finally worked
SELECT
k.Ivalue
, l.JOBDESCRIPTION
, k.TOTAL,
k.CURRENTSTATUS
FROM (
SELECT
a.ID AS Ivalue
,b.ID as JobPostID
, rq."CURRENTSTATUS"
,COUNT(a.ID) AS TOTAL
FROM tblG2o_Requests a
INNER JOIN tblG2o_JOBS b
ON a."JOBPOSTID" = b.ID
INNER JOIN (
SELECT
r."REQUESTID"
, ir."CURRENTSTATUS"
FROM TBLG2O_RESULTSPOOL r
INNER JOIN tblG2o_Requests ir
ON r."REQUESTID" = ir.ID
WHERE r."SHORTLISTED" = 1
) rq
ON rq."REQUESTID" = a.ID
WHERE ACTIVE = '1'
AND DATECOMPLETED IS NULL
GROUP BY
a.ID ,b.ID
, rq."CURRENTSTATUS" ) k
inner join tblG2o_JOBS l on k.JobPostID =l.ID
enter code here

Query for logistic regression, multiple where exists

A logistic regression is a composed of a uniquely identifying number, followed by multiple binary variables (always 1 or 0) based on whether or not a person meets certain criteria. Below I have a query that lists several of these binary conditions. With only four such criteria the query takes a little longer to run than what I would think. Is there a more efficient approach than below? Note. tblicd is a large table lookup table with text representations of 15k+ rows. The query makes no real sense, just a proof of concept. I have the proper indexes on my composite keys.
select patient.patientid
,case when exists
(
select c.patientid from tblclaims as c
inner join patient as p on p.patientid=c.patientid
and c.admissiondate = p.admissiondate
and c.dischargedate = p.dischargedate
where patient.patientid = p.patientid
group by c.patientid
having count(*) > 1000
)
then '1' else '0'
end as moreThan1000
,case when exists
(
select c.patientid from tblclaims as c
inner join patient as p on p.patientid=c.patientid
and c.admissiondate = p.admissiondate
and c.dischargedate = p.dischargedate
where patient.patientid = p.patientid
group by c.patientid
having count(*) > 1500
)
then '1' else '0'
end as moreThan1500
,case when exists
(
select distinct picd.patientid from patienticd as picd
inner join patient as p on p.patientid= picd.patientid
and picd.admissiondate = p.admissiondate
and picd.dischargedate = p.dischargedate
inner join tblicd as t on t.icd_id = picd.icd_id
where t.descrip like '%diabetes%' and patient.patientid = picd.patientid
)
then '1' else '0'
end as diabetes
,case when exists
(
select r.patientid, count(*) from patient as r
where r.patientid = patient.patientid
group by r.patientid
having count(*) >1
)
then '1' else '0'
end
from patient
order by moreThan1000 desc
I would start by using subqueries in the from clause:
select q.patientid, moreThan1000, moreThan1500,
(case when d.patientid is not null then 1 else 0 end),
(case when pc.patientid is not null then 1 else 0 end)
from patient p left outer join
(select c.patientid,
(case when count(*) > 1000 then 1 else 0 end) as moreThan1000,
(case when count(*) > 1500 then 1 else 0 end) as moreThan1500
from tblclaims as c inner join
patient as p
on p.patientid=c.patientid and
c.admissiondate = p.admissiondate and
c.dischargedate = p.dischargedate
group by c.patientid
) q
on p.patientid = q.patientid left outer join
(select distinct picd.patientid
from patienticd as picd inner join
patient as p
on p.patientid= picd.patientid and
picd.admissiondate = p.admissiondate and
picd.dischargedate = p.dischargedate inner join
tblicd as t
on t.icd_id = picd.icd_id
where t.descrip like '%diabetes%'
) d
on p.patientid = d.patientid left outer join
(select r.patientid, count(*) as cnt
from patient as r
group by r.patientid
having count(*) >1
) pc
on p.patientid = pc.patientid
order by 2 desc
You can then probably simplify these subqueries more by combining them (for instance "p" and "pc" on the outer query can be combined into one). However, without the correlated subqueries, SQL Server should find it easier to optimize the queries.
Example of left joins as requested...
SELECT
patientid,
ISNULL(CondA.ConditionA,0) as IsConditionA,
ISNULL(CondB.ConditionB,0) as IsConditionB,
....
FROM
patient
LEFT JOIN
(SELECT DISTINCT patientid, 1 as ConditionA from ... where ... ) CondA
ON patient.patientid = CondA.patientID
LEFT JOIN
(SELECT DISTINCT patientid, 1 as ConditionB from ... where ... ) CondB
ON patient.patientid = CondB.patientID
If your Condition queries only return a maximum one row, you can simplify them down to
(SELECT patientid, 1 as ConditionA from ... where ... ) CondA

Mysql query - invalid use of group function

mysql_query("
SELECT
b.id as b_id
FROM
banner b
INNER JOIN
bannerhits bl
ON
b.id = bl.bannerid
AND
bl.userid = '".$this->userid."'
INNER JOIN
bannerhits blog
ON
b.id = blog.bannerid
INNER JOIN
bannerklik bk
ON
b.id = bk.bannerid
WHERE
(
b.placement = '".$place."'
AND
(
b.usertype = '".$usertype."'
OR
b.usertype = ''
)
AND
b.userpostalcode LIKE ',".$postcode.",'
AND
(
b.userage LIKE ',".$ageYears.",'
OR
b.userage IS NULL
)
AND
(
b.maxviewsprday > count(bl.id)
OR
b.maxviewsprday IS NULL
)
AND
b.maxhits > count(blog.id)
AND
b.maxklik > count(bk.id)
".$ubid."
)
OR
remainingshow = '1'
GROUP BY
bl.id,
bk.id,
blog.id
ORDER BY
remainingshow ASC
LIMIT 1
");
Hello.. This tells me, that it is "invalid use of group function" .. what I want to do is to make sure, that when I count my log for clicks and shows of the banner, there has to be fewer rows with the bannerid=b.id in the log, than the fields b.maxklik and b.maxhits says (so I can set e.g. 6000 clicks or 50000 shows for a banner)..
Can you help with a mysql query that should work??
EDIT 2:
Same error
SELECT
bl.id as bl_id,
bk.id as bk_id,
blog.id as blog_id
FROM
banner b
INNER JOIN
bannerhits bl
ON
b.id = bl.bannerid
AND
bl.userid = '".$this->userid."'
INNER JOIN
bannerhits blog
ON
b.id = blog.bannerid
INNER JOIN
bannerklik bk
ON
b.id = bk.bannerid
WHERE
(
b.placement = '".$place."'
AND
(
b.usertype = '".$usertype."'
OR
b.usertype = ''
)
AND
b.userpostalcode LIKE ',".$postcode.",'
AND
(
b.userage LIKE ',".$ageYears.",'
OR
b.userage IS NULL
)
AND
(
b.maxviewsprday > count(bl.id)
OR
b.maxviewsprday IS NULL
)
AND
b.maxhits > count(blog.id)
AND
b.maxklik > count(bk.id)
".$ubid."
)
OR
remainingshow = '1'
GROUP BY
b.id,
bl.id,
bk.id,
blog.id
ORDER BY
remainingshow ASC
LIMIT 1
EDIT 3:
SELECT
b.id as b_id,
b.maxhits as b_maxhits,
b.maxklik as b_maxkli,
b.maxviewsprday as b_maxviewsprday
FROM banner b
JOIN
bannerhits bl
ON
b.id = bl.bannerid
AND
bl.userid = '".$this->userid."'
JOIN
bannerhits blog
ON
b.id = blog.bannerid
JOIN
bannerklik bk
ON
b.id = bk.bannerid
WHERE
(
b.placement = '".$place."'
AND
b.usertype IN ('".$usertype."', '')
AND
b.userpostalcode LIKE ',".$postcode.",'
AND
(
b.userage LIKE ',".$ageYears.",'
OR
b.userage IS NULL
)
AND
b.maxviewsprday IS NULL
)
OR
b.remainingshow = '1'
GROUP BY
bl.id,
bk.id,
blog.id
HAVING
(b.maxhits > count(blog.id) OR b.maxhits = '0')
AND
(b.maxklik > count(bk.id) OR b.maxklik = '0')
AND
(b.maxviewsprday > count(bl.id) OR b.maxviewsprday = '0')
ORDER BY
b.remainingshow ASC
LIMIT
1
You can't use aggregate functions in the WHERE clause - only the HAVING. I did my best to re-write your query as:
SELECT b.id as b_id
FROM BANNER b
JOIN BANNERHITS bl ON b.id = bl.bannerid
AND bl.userid = '".$this->userid."'
JOIN BANNERHITS blog ON b.id = blog.bannerid
JOIN BANNERKLIK bk ON b.id = bk.bannerid
WHERE ( b.placement = '".$place."'
AND b.usertype IN ('".$usertype."', '')
AND b.userpostalcode LIKE ',".$postcode.",'
AND (b.userage LIKE ',".$ageYears.",' OR b.userage IS NULL)
AND b.maxviewsprday IS NULL)
OR remainingshow = '1'
GROUP BY bl.id, bk.id, blog.id
HAVING b.maxhits > count(blog.id)
AND b.maxklik > count(bk.id)
AND b.maxviewsprday > count(bl.id)
ORDER BY remainingshow ASC
LIMIT 1
You appear to have a syntax error here:
AND b.maxklik > count(bk.id) ".$ubid.")
I don't know how you want to incorporate the $ubid variable into the query...