I have a situation where I am running a query again tables MEMBERS, MEMBERUDFS, and MEMERUDFSETUPS. Where MEMBER UDFs are User Defined Fields that are created by the system admin to store data about customers in customizable fields. The UDFSETUPS table defines the configurable fields and MEMBERUDFS stores the values of those fields if they exist.
The issue I am running into is when I pull data back, I am not getting the rows for entries that have a UDF with an ID of 17 (MEMBERUDFS.udfid = '17') that do not have an entry or are null. I tried Left Joins but it did not seem to help.
SELECT MEMBERS.scancode, MEMBERS.fname, MEMBERS.lname, MEMBERS.datejoin, MEMBERS.entrydate
, MEMBERS.relationship, MEMBERUDFS.udfvalue
FROM MEMBERS
LEFT OUTER JOINMEMBERUDFS
ON MEMBERS.memid = MEMBERUDFS.memid
INNER JOIN MEMBERUDFSETUPS
ON MEMBERUDFS.udfid = MEMBERUDFSETUPS.udfid
WHERE (MEMBERS.siteid = #rvSite)
AND (MEMBERS.status = 'A')
AND (MEMBERS.relationship = 'M')
AND (MEMBERUDFS.udfid = '17')
AND (MEMBERS.datejoin BETWEEN #rvStartDate AND #rvEndDate)
AND (MEMBERS.mtypeid NOT IN (5, 6, 7, 11, 14, 31))
OR (MEMBERS.siteid = #rvSite)
AND (MEMBERS.relationship = 'P')
AND (MEMBERUDFS.udfid = '17')
AND (MEMBERS.entrydate BETWEEN #rvStartDate AND #rvEndDate)
Move the limit on the JoinMemberUDFS to the join or your nulls get excluded.
Preferred method move filter to join criteria
SELECT MEMBERS.scancode, MEMBERS.fname, MEMBERS.lname, MEMBERS.datejoin, MEMBERS.entrydate
, MEMBERS.relationship, MEMBERUDFS.udfvalue
FROM MEMBERS
LEFT JOIN MEMBERUDFS
ON MEMBERS.memid = MEMBERUDFS.memid
AND MEMBERUDFS.udfid = '17'
LEFT JOIN MEMBERUDFSETUPS
ON MEMBERUDFS.udfid = MEMBERUDFSETUPS.udfid
WHERE (MEMBERS.siteid = #rvSite
AND MEMBERS.status = 'A'
AND MEMBERS.relationship = 'M'
AND MEMBERS.datejoin BETWEEN #rvStartDate AND #rvEndDate
AND MEMBERS.mtypeid NOT IN (5, 6, 7, 11, 14, 31))
OR (MEMBERS.siteid = #rvSite
AND MEMBERS.relationship = 'P'
AND MEMBERS.entrydate BETWEEN #rvStartDate AND #rvEndDate)
Not preferred handle when it's null and ensure it returns true for the evaluation
SELECT MEMBERS.scancode, MEMBERS.fname, MEMBERS.lname, MEMBERS.datejoin, MEMBERS.entrydate
, MEMBERS.relationship, MEMBERUDFS.udfvalue
FROM MEMBERS
LEFT OUTER JOINMEMBERUDFS
ON MEMBERS.memid = MEMBERUDFS.memid
INNER JOIN MEMBERUDFSETUPS
ON MEMBERUDFS.udfid = MEMBERUDFSETUPS.udfid
WHERE (MEMBERS.siteid = #rvSite
AND MEMBERS.status = 'A'
AND MEMBERS.relationship = 'M'
AND MEMBERS.datejoin BETWEEN #rvStartDate AND #rvEndDate
AND MEMBERS.mtypeid NOT IN (5, 6, 7, 11, 14, 31)
AND (MEMBERUDFS.udfid = '17' or MEMBERUDFS.udfid is null)
OR (MEMBERS.siteid = #rvSite
AND MEMBERS.relationship = 'P'
AND MEMBERS.entrydate BETWEEN #rvStartDate AND #rvEndDate)
AND (MEMBERUDFS.udfid = '17' or MEMBERUDFS.udfid is null)
Related
This seems like a rather complicated SQL query, from my limited experience.
How could I add or edit this query so that it would include the date being checked in the subqueries via either ees.cardate or s3ees.cardate?
This is one of the subqueries I might be able to qrab the cardate value from:
(EXISTS ( SELECT
s3esc.carstage_model_id
FROM
carstage_model s3esc
JOIN car_carstage s3ees USING (car_carstage_id)
WHERE
s3esc.car_model_id = ec1.car_model_id
AND (s3esc.carmodelstatus_id = ANY (ARRAY[6, 8, 9, 11, 12]))
AND s3ees.cardate >= '2020-07-23 02:55:50.552513'
)
)
Here's the complete query:
WITH running_carmodel(car_model_id, rm_factory_id, factory_id, parent_id, model_id, rm_model_id, firstname, nickname, middlename, lastname, suffix, modelpreferredname_id, title, rank) AS (
SELECT ec.car_model_id, ecp.factory_id, ec.factory_id AS rm_factory_id, ec.parent_id, ec.model_id, ecp.model_id AS rm_model_id, c.firstname, c.nickname, c.middlename, c.lastname, c.suffix, c.modelpreferredname_id, o.title, o.rank
FROM car_model ec
JOIN car e USING (car_id), model c, factory o, car_model ecp
WHERE e.caryear::double precision >= date_part('year'::text, now())
AND ecp.model_id = c.model_id
AND ecp.factory_id = o.factory_id
AND ecp.car_model_id = ec.parent_id
)
SELECT DISTINCT
1 AS q,
ot.rank AS ot_rank,
o.rank AS o_rank,
CASE
WHEN c.model_id IS NOT NULL THEN odn.rank
ELSE dn.rank
END AS dn_rank,
o.factory_id,
oc.state_id,
c.model_id,
CASE
WHEN c.model_id IS NOT NULL THEN odn.districtname_id
ELSE dn.districtname_id
END AS districtname_id,
CASE
WHEN true = false THEN true
ELSE NULL
END AS redis_new,
c.firstname,
c.nickname,
c.middlename,
c.lastname,
c.suffix,
c.modelpreferredname_id,
oc.factory_model_id,
o.name AS factory,
o.title,
ot.rank,
CASE
WHEN c.model_id IS NOT NULL AND oc.districtname_id IS NULL THEN ''::character varying
WHEN dn.name::text ~ '^[0-9]+$'::text THEN ('District '::text || dn.name::text)::character varying
ELSE dn.name
END AS district,
ot.name AS factorytype,
ot.factorytype_id,
c.photourl,
pvs_factory_party(oc.factory_model_id) AS factory_party,
(SELECT
ecs.name
FROM
carmodelstatus ecs
JOIN carstage_model esc USING (carmodelstatus_id)
JOIN car_carstage ees USING (car_carstage_id)
JOIN carstage es USING (carstage_id)
JOIN car_model ec USING (car_model_id)
JOIN car e ON e.car_id = ees.car_id AND e.caryear::double precision = date_part('year'::text, now())
WHERE
esc.car_model_id = ec.car_model_id
AND ec.model_id = c.model_id
AND ec.factory_id = o.factory_id
AND (ec.districtname_id = odn.districtname_id OR ec.districtname_id IS NULL OR odn.districtname_id IS NULL)
AND CASE WHEN ec.factory_id = 1 THEN ees.state_id = 'NA' ELSE TRUE END
AND ees.modelrelease_id >= 2
ORDER BY es.rank DESC
LIMIT 1) AS car_status,
CASE
WHEN c.model_id IS NOT NULL THEN true
ELSE false
END AS incumbent,
ec1.districtname_id AS car_districtname_id,
rm.rm_model_id AS rm_model_id,
rm.firstname AS rm_firstname,
rm.middlename AS rm_middlename,
rm.nickname AS rm_nickname,
rm.lastname AS rm_lastname,
rm.suffix AS rm_suffix,
rm.title AS rm_title,
pvs_car_party(rm.parent_id) AS rm_party,
rm.modelpreferredname_id AS rm_modelpreferredname_id,
ob.name AS factorybranch,
l.name AS local
FROM
factory_state os
JOIN factory o USING (factory_id)
JOIN factorytype ot USING (factorytype_id)
LEFT JOIN factorybranch ob USING (factorybranch_id)
LEFT JOIN district d USING (factory_id, state_id)
LEFT JOIN districtname dn USING (districtname_id)
LEFT JOIN factory_model oc ON oc.factory_id = o.factory_id AND (oc.state_id = os.state_id OR oc.state_id = 'NA'::bpchar) AND (oc.districtname_id = d.districtname_id OR oc.districtname_id IS NULL ) AND (oc.factorymodelstatus_id = ANY (ARRAY[1, 3, 4]))
LEFT JOIN model c USING (model_id)
LEFT JOIN districtname odn ON odn.districtname_id = oc.districtname_id
LEFT JOIN car_model ec1 ON ec1.model_id = c.model_id AND (EXISTS ( SELECT
s3esc.carstage_model_id
FROM
carstage_model s3esc
JOIN car_carstage s3ees USING (car_carstage_id)
WHERE
s3esc.car_model_id = ec1.car_model_id
AND (s3esc.carmodelstatus_id = ANY (ARRAY[6, 8, 9, 11, 12]))
AND s3ees.cardate >= '2020-07-23 02:55:50.552513'
)
)
LEFT JOIN running_carmodel rm ON rm.car_model_id = ec1.car_model_id AND rm.factory_id = o.factory_id
LEFT JOIN local l USING (local_id)
WHERE (
(
oc.factorymodelstatus_id = ANY (ARRAY[1, 4])
OR oc.factory_model_id IS NULL
)
AND (os.state_id = ANY (ARRAY['ME'::bpchar, 'NA'::bpchar]))
AND
CASE
WHEN o.factory_id = ANY (ARRAY[1, 3, 4, 6]) THEN true
WHEN ot.factorytype_id = 'P'::bpchar THEN true
WHEN o.factory_id = 5 THEN (dn.districtname_id IN (1) OR dn.districtname_id IN (978, 910, 917, 370))
WHEN o.factory_id = 6 THEN dn.districtname_id IN (613, 914, 915, 2019, 2020)
WHEN o.factory_id IN (7,8) THEN dn.districtname_id IN (36,37,40,41,42,43)
WHEN o.factory_id = 9 THEN dn.districtname_id IN (25,27,28)
WHEN ot.factorylevel_id = 'S'::bpchar THEN true
WHEN ot.factorylevel_id = 'L'::bpchar AND oc.local_id IN (619,2438) THEN true
ELSE false
END
)
UNION
SELECT DISTINCT
2 AS q,
ot.rank AS ot_rank,
o.rank AS o_rank,
dn.rank AS dn_rank,
o.factory_id,
ec.state_id,
c.model_id,
CASE
WHEN o.factory_id = 6 THEN ( SELECT
s2ec.districtname_id
FROM
car_model s2ec
JOIN carstage_model s2esc USING (car_model_id)
WHERE
(s2esc.carmodelstatus_id = ANY (ARRAY[6, 7, 8, 9, 10, 11, 12, 13]))
AND s2ec.factory_id = 6
AND s2ec.state_id = ec.state_id
LIMIT 1)
ELSE dn.districtname_id
END AS districtname_id,
false AS redis_new,
c.firstname,
c.nickname,
c.middlename,
c.lastname,
c.suffix,
c.modelpreferredname_id,
ec.car_model_id AS factory_model_id,
o.name AS factory,
o.title,
ot.rank,
CASE
WHEN dn.name::text ~ '^[0-9]+$'::text THEN ('District '::text || dn.name::text)::character varying
ELSE dn.name
END AS district,
ot.name AS factorytype,
ot.factorytype_id,
c.photourl,
pvs_car_party(ec.car_model_id) AS factory_party,
(SELECT ssecs.name
FROM carmodelstatus ssecs
JOIN carstage_model ssesc USING (carmodelstatus_id)
JOIN car_carstage ssees USING (car_carstage_id)
JOIN carstage sses USING (carstage_id)
WHERE
ssesc.car_model_id = ec.car_model_id
AND CASE
WHEN o.factory_id = 1 THEN sses.carstage_id = 'G'::bpchar AND ssees.state_id = 'NA'
ELSE true
END
AND ssees.modelrelease_id >= 2
ORDER BY sses.rank DESC
LIMIT 1) AS car_status,
(SELECT true AS bool
FROM factory_model s3oc
JOIN factory s3o USING (factory_id)
WHERE
s3oc.factory_id = ec.factory_id
AND (
s3oc.districtname_id = ec.districtname_id
OR s3oc.districtname_id IS NULL
OR ec.factory_id = 6
OR s3o.factorytype_id = 'K'::bpchar
AND ec.state_id = 'ME'::bpchar
)
AND s3oc.state_id = ec.state_id
AND s3oc.model_id = c.model_id
AND s3oc.factorymodelstatus_id IN (1,4)
LIMIT 1) AS incumbent,
(-1) AS car_districtname_id,
rm.rm_model_id AS rm_model_id,
rm.firstname AS rm_firstname,
rm.middlename AS rm_middlename,
rm.nickname AS rm_nickname,
rm.lastname AS rm_lastname,
rm.suffix AS rm_suffix,
rm.title AS rm_title,
pvs_car_party(rm.parent_id) AS rm_party,
rm.modelpreferredname_id AS rm_modelpreferredname_id,
ob.name AS factorybranch,
NULL AS local
FROM
model c
JOIN car_model ec USING (model_id)
JOIN car e ON e.car_id = ec.car_id
JOIN factory o USING (factory_id)
JOIN factorytype ot ON ot.factorytype_id = o.factorytype_id
JOIN car_carstage ees ON ees.car_id = e.car_id AND ees.state_id = ec.state_id
JOIN carstage_model esc USING (car_model_id, car_carstage_id)
LEFT JOIN factorybranch ob USING (factorybranch_id)
LEFT JOIN running_carmodel rm ON rm.car_model_id = ec.car_model_id
LEFT JOIN districtname dn USING (districtname_id)
WHERE
(ec.state_id = ANY (ARRAY['ME'::bpchar, 'NA'::bpchar]))
AND ees.cardate >= '2020-07-23 02:55:50.552513'
AND CASE
WHEN o.factory_id = 1 THEN ec.major
WHEN o.factory_id = 2 THEN (EXISTS ( SELECT s6ec.car_model_id
FROM car_model s6ec
JOIN carstage_model s6esc USING (car_model_id)
WHERE (
s6esc.carmodelstatus_id = ANY (ARRAY[6, 8, 9, 11, 12]))
AND s6ec.model_id = ec.parent_id
AND s6ec.major = true
)
)
WHEN o.factory_id = ANY (ARRAY[3, 4, 6]) THEN true
WHEN ot.factorytype_id = 'P'::bpchar THEN true
WHEN o.factory_id = 5 THEN (dn.districtname_id IN (1) OR dn.districtname_id IN (978, 910, 917, 370))
WHEN o.factory_id = 6 THEN dn.districtname_id IN (613, 914, 915, 2019, 2020)
WHEN o.factory_id IN (7,8) THEN dn.districtname_id IN (36,37,40,41,42,43)
WHEN o.factory_id = 9 THEN dn.districtname_id IN (25,27,28)
WHEN ot.factorylevel_id = 'S'::bpchar THEN true
ELSE false
END
AND ees.modelrelease_id >= 1
AND e.caryear >= 2020
ORDER BY 1, 2, 3, 4, 18, 13
The below code throws the following exception. How can I fix this?
Msg 8156, Level 16, State 1, Line 17
The column 'id' was specified multiple times for 'QISproduct'.
Query:
SELECT
g.artcode
, sum(g.aantal)
, i.class_01
, i.Isstockitem
FROM
gbkmut AS g
INNER JOIN
items AS i ON i.itemcode = g.artcode
INNER JOIN
(SELECT
QISP.id
, QISprocess.nml
, QISeventlog.id
, QISeventlog.dtsample
, QISproduct.nms
, QISbatchlog.nm
, QIStestlog.idvariable
, QIStestlog.no
, QISshortnote.ds
, gewicht = CASE QIStestlog.IDvariable
WHEN '139'
THEN QIStestlog.no
END
, aantal = CASE QIStestlog.IDvariable
WHEN '234'
THEN QIStestlog.no
END
, siloleeg = CASE QIStestlog.idvariable
WHEN '23'
THEN CASE QIStestlog.no
WHEN '10'
THEN 'Ja'
ELSE 'Nee'
END
END
, QISvariable.nml
, gl.nm
, QISprocess.id
FROM
QIC.Vobra_new2.dbo.production AS QISP
INNER JOIN
QIC.Vobra_new2.dbo.process AS QISprocess ON QISP.idprocess = QISProcess.id
INNER JOIN
QIC.Vobra_new2.dbo.product AS QISproduct ON QISP.idproduct = QISproduct.id
INNER JOIN
QIC.Vobra_new2.dbo.batchlog AS QISbatchlog ON QISP.idbatch = QISbatchlog.id
INNER JOIN
QIC.Vobra_new2.dbo.eventlog AS QISeventlog ON QISeventlog.idproduction = QISP.id
AND QISeventlog.idbatch = QISbatchlog.id
INNER JOIN
QIC.Vobra_new2.dbo.testlog AS QIStestlog ON QIStestlog.idevent = QISeventlog.id
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.shortnote AS QISshortnote ON QISshortnote.id = QIStestlog.no
AND QIStestlog.idvariable = '144'
INNER JOIN
QIC.Vobra_new2.dbo.variable AS QISvariable ON QISvariable.id = QIStestlog.idvariable
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.vvarxproc AS vvp ON vvp.idvariable = QISvariable.id
AND vvp.idprocess = QISP.idprocess
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.attribute AS QISattribute ON QISattribute.id = vvp.idattribute
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.grade AS QISgrade ON QISgrade.id = QISattribute.idgrade
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.gradelevel AS gl ON gl.idgrade = QISattribute.idgrade
AND gl.nlevel = QIStestlog.no
WHERE
QISbatchlog.nm NOT LIKE 'V%'
AND QISP.dtstart > '2017-01-01'
AND QISP.dtstart < '2017-01-19'
AND QISP.idprocess IN ('12', '13', '14', '15', '16', '17', '18', '41')
AND QIStestlog.idvariable IN ('234', '139', '128')
) QISproduct ON g.artcode = QISproduct.nms
WHERE
g.bkjrcode > '2015'
AND g.reknr IN (3000, 3010, 3020)
AND g.aantal > 0
AND g.warehouse IN ('1', '9')
AND g.datum >= '2017-01-01'
AND g.oorsprong = 'R'
AND g.kstplcode <> 'VPR'
GROUP BY
g.artcode, i.Class_01, i.IsStockItem
The computed query aliased to QISProduct contains id column from two tables i.e. QISEventLog and QISProcess. So rename those columns to different names. Updated query
SELECT g.artcode
,sum(g.aantal)
,i.class_01
,i.Isstockitem
FROM gbkmut AS g
INNER JOIN items AS i ON i.itemcode = g.artcode
INNER JOIN (
SELECT QISP.id
,QISprocess.nml AS Processnml
,QISeventlog.id AS EventLogId
,QISeventlog.dtsample
,QISproduct.nms
,QISbatchlog.nm AS batchnm
,QIStestlog.idvariable
,QIStestlog.no
,QISshortnote.ds
,gewicht = CASE QIStestlog.IDvariable
WHEN '139'
THEN QIStestlog.no
END
,aantal = CASE QIStestlog.IDvariable
WHEN '234'
THEN QIStestlog.no
END
,siloleeg = CASE QIStestlog.idvariable
WHEN '23'
THEN CASE QIStestlog.no
WHEN '10'
THEN 'Ja'
ELSE 'Nee'
END
END
,QISvariable.nml variablenml
,gl.nm AS glnm
,QISprocess.id AS ProcessId
FROM QIC.Vobra_new2.dbo.production AS QISP
INNER JOIN QIC.Vobra_new2.dbo.process AS QISprocess ON QISP.idprocess = QISProcess.id
INNER JOIN QIC.Vobra_new2.dbo.product AS QISproduct ON QISP.idproduct = QISproduct.id
INNER JOIN QIC.Vobra_new2.dbo.batchlog AS QISbatchlog ON QISP.idbatch = QISbatchlog.id
INNER JOIN QIC.Vobra_new2.dbo.eventlog AS QISeventlog ON QISeventlog.idproduction = QISP.id
AND QISeventlog.idbatch = QISbatchlog.id
INNER JOIN QIC.Vobra_new2.dbo.testlog AS QIStestlog ON QIStestlog.idevent = QISeventlog.id
LEFT JOIN QIC.Vobra_new2.dbo.shortnote AS QISshortnote ON QISshortnote.id = QIStestlog.no
AND QIStestlog.idvariable = '144'
INNER JOIN QIC.Vobra_new2.dbo.variable AS QISvariable ON QISvariable.id = QIStestlog.idvariable
LEFT JOIN QIC.Vobra_new2.dbo.vvarxproc AS vvp ON vvp.idvariable = QISvariable.id
AND vvp.idprocess = QISP.idprocess
LEFT JOIN QIC.Vobra_new2.dbo.attribute AS QISattribute ON QISattribute.id = vvp.idattribute
LEFT JOIN QIC.Vobra_new2.dbo.grade AS QISgrade ON QISgrade.id = QISattribute.idgrade
LEFT JOIN QIC.Vobra_new2.dbo.gradelevel AS gl ON gl.idgrade = QISattribute.idgrade
AND gl.nlevel = QIStestlog.no
WHERE QISbatchlog.nm NOT LIKE 'V%'
AND QISP.dtstart > '2017-01-01'
AND QISP.dtstart < '2017-01-19'
AND QISP.idprocess IN (
'12'
,'13'
,'14'
,'15'
,'16'
,'17'
,'18'
,'41'
)
AND QIStestlog.idvariable IN (
'234'
,'139'
,'128'
)
) QISproduct ON g.artcode = QISproduct.nms
WHERE g.bkjrcode > '2015'
AND g.reknr IN (
3000
,3010
,3020
)
AND g.aantal > 0
AND g.warehouse IN (
'1'
,'9'
)
AND g.datum >= '2017-01-01'
AND g.oorsprong = 'R'
AND g.kstplcode <> 'VPR'
GROUP BY g.artcode
,i.Class_01
,i.IsStockItem
, QISbatchlog.nm
And
, gl.nm
Have same column name
You can add as to change colum name
, gl.nm as col1
You have multiple issues in your query. You are populating following columns with same column name in your inner query. Use Unique name using AS alias in inner query.
QISP.id
QISeventlog.id
QISprocess.id
gl.nm
QISbatchlog.nm
QISprocess.nml
QISvariable.nml
It is mandatory to have unique column name return by select list in sql.
I have a situation where I need to select prospects (relationship of 'P') from our MEMBERS table for a particular site. However, when I select these people, I need to exclude two groups of those prospects. Each of these groups have entries in a separate table named MEMBERUDFS. Now not all entries in the MEMBERS table will have an entry in the MEMBERUDFS table. Therefore, I tried to exclude those groups from the main query by using two "NOT IN" subqueries but that does not seem to work. I am able to isolate the exclusion group with the following queries:
SELECT MEMBERS_1.memid
FROM MEMBERS AS MEMBERS_1
JOIN SITES AS SITES_1 ON MEMBERS_1.siteid = SITES_1.siteid
LEFT JOIN MEMBERUDFS AS MEMBERUDFS_1 ON MEMBERS_1.memid = MEMBERUDFS_1.memid
JOIN MEMBERUDFSETUPS AS MEMBERUDFSETUPS_1 ON MEMBERUDFS_1.udfid = MEMBERUDFSETUPS_1.udfid
WHERE (MEMBERS_1.relationship = 'P')
AND (MEMBERS_1.email <> '')
AND (MEMBERUDFS_1.udfid = '26')
AND (MEMBERUDFS_1.udfvalue = 'No')
AND (MEMBERS_1.entrydate < DATEADD(DAY, -6, GETDATE()))
AND (MEMBERS_1.siteid = #rvSite)
And This query:
SELECT MEMBERS_2.memid
FROM MEMBERS AS MEMBERS_2
JOIN SITES AS SITES_2 ON MEMBERS_2.siteid = SITES_2.siteid
LEFT JOIN MEMBERUDFS AS MEMBERUDFS_2 ON MEMBERS_2.memid = MEMBERUDFS_2.memid
JOIN MEMBERUDFSETUPS AS MEMBERUDFSETUPS_2 ON MEMBERUDFS_2.udfid = MEMBERUDFSETUPS_2.udfid
WHERE (MEMBERS_2.relationship = 'P')
AND (MEMBERS_2.email <> '')
AND (MEMBERUDFS_2.udfid = '25')
AND (MEMBERUDFS_2.udfvalue = 'Yes')
AND (MEMBERS_2.entrydate < DATEADD(DAY, -21, GETDATE()))
AND (MEMBERS_2.siteid = #rvSite)
SO THIS IS WHAT I HAD PUT TOGETHER, BUT IT DOES NOT ELIMINATE THE TWO SUBQUERY GROUPS:
SELECT MEMBERS.scancode,
MEMBERS.memid,
MEMBERS.fname,
MEMBERS.lname,
MEMBERS.relationship,
MEMBERS.status,
MEMBERS.email,
MEMBERS.entrydate,
SITES.sitename
FROM MEMBERS
JOIN SITES ON MEMBERS.siteid = SITES.siteid
WHERE (MEMBERS.relationship = 'P')
AND (MEMBERS.email <> '')
AND (MEMBERS.siteid = #rvSite)
AND (MEMBERS.memid NOT IN (
SELECT MEMBERS_1.memid
FROM MEMBERS AS MEMBERS_1
JOIN SITES AS SITES_1 ON MEMBERS_1.siteid = SITES_1.siteid
LEFT JOIN MEMBERUDFS AS MEMBERUDFS_1 ON MEMBERS_1.memid = MEMBERUDFS_1.memid
JOIN MEMBERUDFSETUPS AS MEMBERUDFSETUPS_1 ON MEMBERUDFS_1.udfid = MEMBERUDFSETUPS_1.udfid
WHERE (MEMBERS_1.relationship = 'P')
AND (MEMBERS_1.email <> '')
AND (MEMBERUDFS_1.udfid = '26')
AND (MEMBERUDFS_1.udfvalue = 'No')
AND (MEMBERS_1.entrydate < DATEADD(DAY, -6, GETDATE()))
AND (MEMBERS_1.siteid = #rvSite))
)
AND (MEMBERS.memid NOT IN (
SELECT MEMBERS_2.memid
FROM MEMBERS AS MEMBERS_2
JOIN SITES AS SITES_2 ON MEMBERS_2.siteid = SITES_2.siteid
LEFT JOIN MEMBERUDFS AS MEMBERUDFS_2 ON MEMBERS_2.memid = MEMBERUDFS_2.memid
JOIN MEMBERUDFSETUPS AS MEMBERUDFSETUPS_2 ON MEMBERUDFS_2.udfid = MEMBERUDFSETUPS_2.udfid
WHERE (MEMBERS_2.relationship = 'P')
AND (MEMBERS_2.email <> '')
AND (MEMBERUDFS_2.udfid = '25')
AND (MEMBERUDFS_2.udfvalue = 'Yes')
AND (MEMBERS_2.entrydate < DATEADD(DAY, -21, GETDATE()))
AND (MEMBERS_2.siteid = #rvSite))
)
Any help would be appreciated
You just need to play with your where clause...
AND (MEMBERS.memid NOT IN (
SELECT MEMBERS_1.memid
FROM MEMBERS AS MEMBERS_1
JOIN SITES AS SITES_1 ON MEMBERS_1.siteid = SITES_1.siteid
LEFT JOIN MEMBERUDFS AS MEMBERUDFS_1 ON MEMBERS_1.memid = MEMBERUDFS_1.memid
JOIN MEMBERUDFSETUPS AS MEMBERUDFSETUPS_1 ON MEMBERUDFS_1.udfid = MEMBERUDFSETUPS_1.udfid
WHERE (MEMBERS_1.relationship = 'P')
AND (MEMBERS_1.email <> '')
AND (MEMBERS_1.siteid = #rvSite)
AND (((MEMBERUDFS_1.udfid = '26') AND (MEMBERUDFS_1.udfvalue = 'No') AND (MEMBERS_1.entrydate < DATEADD(DAY, -6, GETDATE()))) OR
((MEMBERUDFS_1.udfid = '25') AND (MEMBERUDFS_1.udfvalue = 'Yes') AND (MEMBERS_1.entrydate < DATEADD(DAY, -21, GETDATE()))))
I have this query, it returns 570 rows, but runs 2m 35s. In SQL the query execute, but in my solution, it gives a timeout. How can I optimize this to run under 1m, pref 30s.
SELECT [Region] = Region.FirstName,
[Patient] = Patient.Name,
[PatientStatus] = AccountRating.Name,
[MedicalAid] = AccountType.Name,
[QuoteAmount] = ( SELECT TOP 1 A.Response
FROM dbo.Questionnaire Q
JOIN dbo.QuestionnaireDefinition QRD
ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID
AND QRD.Name = 'Internal Admin'
LEFT JOIN QuestionDefinition QD
ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID
AND QD.QuestionDefinitionID = 5966
LEFT OUTER JOIN Answer A
ON A.QuestionnaireID = Q.QuestionnaireID
AND A.QuestionDefinitionID = QD.QuestionDefinitionID
WHERE Q.IsActive = 1
AND Q.SubscriberID = 240
AND Q.AccountID = Patient.AccountID
),
[InvoiceAmount] = ( SELECT TOP 1 A.Response
FROM dbo.Questionnaire Q
JOIN dbo.QuestionnaireDefinition QRD
ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID
AND QRD.Name = 'Internal Admin'
LEFT JOIN QuestionDefinition QD
ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID
AND QD.QuestionDefinitionID = 5969
LEFT OUTER JOIN Answer A
ON A.QuestionnaireID = Q.QuestionnaireID
AND A.QuestionDefinitionID = QD.QuestionDefinitionID
WHERE Q.IsActive = 1
AND Q.SubscriberID = 240
AND Q.AccountID = Patient.AccountID
),
[DateSubmitted] = ( SELECT TOP 1 A.Response
FROM dbo.Questionnaire Q
JOIN dbo.QuestionnaireDefinition QRD
ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID
AND QRD.Name = 'Internal Admin'
LEFT JOIN QuestionDefinition QD
ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID
AND QD.QuestionDefinitionID = 5965
LEFT OUTER JOIN Answer A
ON A.QuestionnaireID = Q.QuestionnaireID
AND A.QuestionDefinitionID = QD.QuestionDefinitionID
WHERE Q.IsActive = 1
AND Q.SubscriberID = 240
AND Q.AccountID = Patient.AccountID
),
[DateApprovedDeclined] = ( SELECT TOP 1 A.Response
FROM dbo.Questionnaire Q
JOIN dbo.QuestionnaireDefinition QRD
ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID
AND QRD.Name = 'Internal Admin'
LEFT JOIN QuestionDefinition QD
ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID
AND QD.QuestionDefinitionID = 5968
LEFT OUTER JOIN Answer A
ON A.QuestionnaireID = Q.QuestionnaireID
AND A.QuestionDefinitionID = QD.QuestionDefinitionID
WHERE Q.IsActive = 1
AND Q.SubscriberID = 240
AND Q.AccountID = Patient.AccountID
),
[IntAdmFormCreatedDate]= Q.DateCreated,
[HasAdminForm] = 'Yes',
[CreatedByUser] = PatientCreatedBy.Name
FROM dbo.Account AS Patient
JOIN dbo.AccountRating
ON Patient.AccountRatingID = AccountRating.AccountRatingID
JOIN dbo.AccountType
ON Patient.AccountTypeID = AccountType.AccountTypeID
JOIN dbo.[User] Region
ON Patient.UserID = Region.UserID
JOIN dbo.[User] PatientCreatedBy
ON Patient.CreatedBy = PatientCreatedBy.UserID
JOIN dbo.Questionnaire Q
ON Patient.AccountID = Q.AccountID
WHERE Patient.SubscriberID = 240
AND (Q.DateCreated < DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102))))
AND Q.QuestionnaireDefinitionID = 235
AND Q.IsActive = 1
AND Region.FirstName <> 'Rubbish'
UNION SELECT [Region] = Region.FirstName,
[Patient] = Patient.Name,
[PatientStatus] = AccountRating.Name,
[MedicalAid] = AccountType.Name,
[QuoteAmount] = '0',
[InvoiceAmount] = '0',
[DateSubmitted] = '',
[DateApprovedDeclined] = '',
[IntAdmFormCreatedDate] = '',
[HasAdminForm] = 'No',
[CreatedByUser] = PatientCreatedBy.Name
FROM dbo.Account AS Patient
JOIN dbo.AccountRating
ON Patient.AccountRatingID = AccountRating.AccountRatingID
JOIN dbo.AccountType
ON Patient.AccountTypeID = AccountType.AccountTypeID
JOIN dbo.[User] AS Region
ON Patient.UserID = Region.UserID
JOIN dbo.[User] AS PatientCreatedBy
ON Patient.CreatedBy = PatientCreatedBy.UserID
WHERE NOT EXISTS( SELECT *
FROM Questionnaire AS Q
WHERE Patient.AccountID = Q.AccountID
AND Q.QuestionnaireDefinitionID = 235
AND Patient.SubscriberID = 240
AND Q.SubscriberID = 240
)
AND Patient.SubscriberID = 240
AND Patient.DateCreated < DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102)))
AND Region.FirstName <> 'Rubbish'
Here is another version of the query I tried, but also runs the same time.
SELECT [Region] = Region.FirstName,
[Patient] = Patient.Name,
[PatientStatus] = AccountRating.Name,
[MedicalAid] = AccountType.Name,
[QuoteAmount] = Q1.Response,
[InvoiceAmount] = Q2.Response,
[DateSubmitted] = Q3.Response,
[DateApprovedDeclined] = Q4.Response,
[IntAdmFormCreatedDate]= Q.DateCreated,
[HasAdminForm] = 'Yes',
[CreatedByUser] = PatientCreatedBy.Name
FROM dbo.Account AS Patient
JOIN dbo.AccountRating
ON Patient.AccountRatingID = AccountRating.AccountRatingID
JOIN dbo.AccountType
ON Patient.AccountTypeID = AccountType.AccountTypeID
JOIN dbo.[User] Region
ON Patient.UserID = Region.UserID
JOIN dbo.[User] PatientCreatedBy
ON Patient.CreatedBy = PatientCreatedBy.UserID
JOIN dbo.Questionnaire Q
ON Patient.AccountID = Q.AccountID
OUTER APPLY
(
SELECT TOP 1 Q.AccountID,
A.Response
FROM dbo.Questionnaire Q
JOIN dbo.QuestionnaireDefinition QRD
ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID
AND QRD.Name = 'Internal Admin'
LEFT JOIN QuestionDefinition QD
ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID
AND QD.QuestionDefinitionID = 5966
LEFT OUTER JOIN Answer A
ON A.QuestionnaireID = Q.QuestionnaireID
AND A.QuestionDefinitionID = QD.QuestionDefinitionID
WHERE Q.IsActive = 1
Q.SubscriberID = 240
AND Q.AccountID = Patient.AccountID
) Q1
OUTER APPLY
(
SELECT TOP 1 Q.AccountID,
A.Response
FROM dbo.Questionnaire Q
JOIN dbo.QuestionnaireDefinition QRD
ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID
AND QRD.Name = 'Internal Admin'
LEFT JOIN QuestionDefinition QD
ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID
AND QD.QuestionDefinitionID = 5969
LEFT OUTER JOIN Answer A
ON A.QuestionnaireID = Q.QuestionnaireID
AND A.QuestionDefinitionID = QD.QuestionDefinitionID
WHERE Q.IsActive = 1
AND Q.AccountID = Patient.AccountID
) Q2
OUTER APPLY
(
SELECT TOP 1 Q.AccountID,
A.Response
FROM dbo.Questionnaire Q
JOIN dbo.QuestionnaireDefinition QRD
ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID
AND QRD.Name = 'Internal Admin'
LEFT JOIN QuestionDefinition QD
ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID
AND QD.QuestionDefinitionID = 5965
LEFT OUTER JOIN Answer A
ON A.QuestionnaireID = Q.QuestionnaireID
AND A.QuestionDefinitionID = QD.QuestionDefinitionID
WHERE Q.IsActive = 1
AND Q.AccountID = Patient.AccountID
) Q3
OUTER APPLY
(
SELECT TOP 1 Q.AccountID,
A.Response
FROM dbo.Questionnaire Q
JOIN dbo.QuestionnaireDefinition QRD
ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID
AND QRD.Name = 'Internal Admin'
LEFT JOIN QuestionDefinition QD
ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID
AND QD.QuestionDefinitionID = 5968
LEFT OUTER JOIN Answer A
ON A.QuestionnaireID = Q.QuestionnaireID
AND A.QuestionDefinitionID = QD.QuestionDefinitionID
WHERE Q.IsActive = 1
AND Q.AccountID = Patient.AccountID
) Q4
WHERE Patient.SubscriberID = 240
AND (Q.DateCreated < DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102))))
AND Q.QuestionnaireDefinitionID = 235
AND Q.IsActive = 1
AND Region.FirstName <> 'Rubbish'
UNION SELECT [Region] = Region.FirstName,
[Patient] = Patient.Name,
[PatientStatus] = AccountRating.Name,
[MedicalAid] = AccountType.Name,
[QuoteAmount] = '0',
[InvoiceAmount] = '0',
[DateSubmitted] = '',
[DateApprovedDeclined] = '',
[IntAdmFormCreatedDate] = '',
[HasAdminForm] = 'No',
[CreatedByUser] = PatientCreatedBy.Name
FROM dbo.Account AS Patient
JOIN dbo.AccountRating
ON Patient.AccountRatingID = AccountRating.AccountRatingID
JOIN dbo.AccountType
ON Patient.AccountTypeID = AccountType.AccountTypeID
JOIN dbo.[User] AS Region
ON Patient.UserID = Region.UserID
JOIN dbo.[User] AS PatientCreatedBy
ON Patient.CreatedBy = PatientCreatedBy.UserID
WHERE NOT EXISTS( SELECT *
FROM Questionnaire AS Q
WHERE Patient.AccountID = Q.AccountID
AND Q.QuestionnaireDefinitionID = 235
AND Patient.SubscriberID = 240
AND Q.SubscriberID = 240
)
AND Patient.SubscriberID = 240
AND Patient.DateCreated < DATEADD(D, 26, DATEADD(MONTH, DATEDIFF(MONTH, CONVERT(DATETIME, '1900-01-01 00:00:00', 102), GETDATE()), CONVERT(DATETIME, '1900-01-01 00:00:00', 102)))
AND Region.FirstName <> 'Rubbish'
Your Scalar Subqueries all share the same joins, just the QD.QuestionDefinitionID differs.
You can rewrite those 4 TOPs with a single Derived Table and join to it instead:
...
LEFT JOIN
(
SELECT
Q.AccountID,
MAX(CASE WHEN QD.QuestionDefinitionID = 5966 THEN A.Response END) AS [DateSubmitted]
MAX(CASE WHEN QD.QuestionDefinitionID = 5968 THEN A.Response END) AS [DateApprovedDeclined]
...
FROM dbo.Questionnaire Q
JOIN dbo.QuestionnaireDefinition QRD
ON QRD.QuestionnaireDefinitionID = Q.QuestionnaireDefinitionID
AND QRD.NAME = 'Internal Admin'
LEFT JOIN QuestionDefinition QD
ON Q.QuestionnaireDefinitionID = QD.QuestionnaireDefinitionID
LEFT OUTER JOIN Answer A
ON A.QuestionnaireID = Q.QuestionnaireID
AND A.QuestionDefinitionID = QD.QuestionDefinitionID
WHERE Q.IsActive = 1
AND Q.SubscriberID = 240
GROUP BY Q.AccountID
) AS Q
ON Q.AccountID = Patient.AccountID
I used MAX because you didn't have ORDER BY in you subqueries, so the exact value either doesn't matter or there's only a single row per value.
I need a SQL query that returns results matched by EITHER of the following SQL queries:
Query 1:
SELECT "annotations".* FROM "annotations" INNER JOIN "votes" ON "votes".voteable_id = "annotations".id AND "votes".voteable_type = 'Annotation'
WHERE (votes.vote = 't' AND votes.voter_id = 78)
Query 2:
SELECT "annotations".* FROM "annotations" INNER JOIN "songs" ON "songs".id = "annotations".song_id INNER JOIN "songs" songs_annotations ON "songs_annotations".id = "annotations".song_id INNER JOIN "users" ON "users".id = "songs_annotations".state_last_updated_by_id
WHERE (annotations.referent IS NOT NULL AND annotations.updated_at < '2010-04-05 01:51:24' AND (body = '?' OR body LIKE '%[?]%') AND ((users.id = songs.state_last_updated_by_id and users.needs_edit = 'f' and songs.state != 'work_in_progress') OR (songs.state = 'published'))
Here's what I tried, but it doesn't work:
SELECT "annotations".* FROM "annotations" INNER JOIN "songs" ON "songs".id = "annotations".song_id INNER JOIN "songs" songs_annotations ON "songs_annotations".id = "annotations".song_id INNER JOIN "users" ON "users".id = "songs_annotations".state_last_updated_by_id INNER JOIN "votes" ON "votes".voteable_id = "annotations".id AND "votes".voteable_type = 'Annotation' WHERE ((votes.vote = 't' and votes.voter_id = 78) OR (annotations.referent IS NOT NULL and annotations.updated_at < '2010-04-05 01:43:52' and (annotations.body = '?' OR annotations.body LIKE '%[?]%') and ((users.id = songs.state_last_updated_by_id and users.needs_edit = 'f') OR songs.state = 'published')))
UNION is the simplest. If your engine's optimizer doesn't do an efficient job with that, I might look deeper (but anything else would probably involve a lot of LEFT JOINs, since it looks you are joining two distinct uses of annotations):
SELECT "annotations".*
FROM "annotations"
INNER JOIN "votes"
ON "votes".voteable_id = "annotations".id
AND "votes".voteable_type = 'Annotation'
WHERE (votes.vote = 't' AND votes.voter_id = 78)
UNION
SELECT "annotations".*
FROM "annotations"
INNER JOIN "songs"
ON "songs".id = "annotations".song_id
INNER JOIN "songs" songs_annotations
ON "songs_annotations".id = "annotations".song_id
INNER JOIN "users"
ON "users".id = "songs_annotations".state_last_updated_by_id
WHERE (annotations.referent IS NOT NULL
AND annotations.updated_at < '2010-04-05 01:51:24'
AND (body = '?' OR body LIKE '%[?]%')
AND ((users.id = songs.state_last_updated_by_id and users.needs_edit = 'f' and songs.state != 'work_in_progress') OR (songs.state = 'published'))
For the same reason your INNER JOIN attempt failed (all join criteria must be satisfied), you would have to change almost everything to LEFT JOIN (or LEFT JOIN to a nested INNER JOIN) - I think the UNION is simplest.
SELECT "annotations".*
FROM "annotations"
LEFT JOIN "votes"
ON "votes".voteable_id = "annotations".id
AND "votes".voteable_type = 'Annotation'
LEFT JOIN "songs"
ON "songs".id = "annotations".song_id
LEFT JOIN "songs" songs_annotations
ON "songs_annotations".id = "annotations".song_id
LEFT JOIN "users"
ON "users".id = "songs_annotations".state_last_updated_by_id
WHERE (votes.vote = 't' AND votes.voter_id = 78)
OR
(annotations.referent IS NOT NULL
AND annotations.updated_at < '2010-04-05 01:51:24'
AND (body = '?' OR body LIKE '%[?]%')
AND ((users.id = songs.state_last_updated_by_id and users.needs_edit = 'f' and songs.state != 'work_in_progress') OR (songs.state = 'published'))