This question already exists:
Cannot when add ORDER BY in a CTE
Closed 9 months ago.
Is there any way I can reference the inner dense rank results and give them appropriate labels like I am trying to do? It seems like in T-SQL I just can NOT do an "Order by" in an inner query, it is producing an error like:
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
But then how do I attach appropriate labels to the dense rank results in the code below?
WITH basequery AS (
SELECT c.baseentityid,
c.team,
c.providerid,
-- rank() OVER (PARTITION BY c.baseentityid ORDER BY c.version DESC) AS rn,
t.vaccinedate,
t.vaccine,
t.vaccinesource,
t.num
FROM vr.child_registration c
CROSS APPLY ( VALUES (c.bcgsource,c.bcgdate,'bcg',1), (c.opv0source,c.opv0date,'opv0',2), (c.penta1source,c.penta1date,'penta1',3), (c.pcv1source,c.pcv1date,'pcv1',4), (c.rota1source,c.rota1date,'rota1',5), (c.opv1source,c.opv1date,'opv1',6), (c.penta2source,c.penta2date,'penta2',7), (c.pcv2source,c.pcv2date,'pcv2',8), (c.rota2source,c.rota2date,'rota2',9), (c.opv2source,c.opv2date,'opv2',10), (c.penta3source,c.penta3date,'penta3',11), (c.ipvsource,c.ipvdate,'ipv',12), (c.pcv3source,c.pcv3date,'pcv3',13), (c.opv3source,c.opv3date,'opv3',14), (c.measles1source,c.measles1date,'measles1',15), (c.tcvsource,c.tcvdate,'tcv',16), (c.ipv2source,c.ipv2date,'ipv2',17), (c.measles2source,c.measles2date,'measles2',18)) t(vaccinesource, vaccinedate, vaccine, num)
WHERE t.vaccinedate IS NOT NULL AND t.vaccinedate <> ''
)
SELECT aa.baseentityid,
aa.team,
aa.vaccinedate,
aa.vaccine,
aa.vaccinesource,
aa.num,
aa.providerid,
aa.visitrank,
CASE
WHEN aa.visitrank = 0 THEN 'external vaccination'
WHEN aa.visitrank = 1 THEN 'Enrollment'
ELSE 'Visitation'
END AS visittype,
CASE
WHEN aa.providerid LIKE '%vacc%' THEN 'Vacc'
ELSE 'Non-Vacc'
END AS providertype
FROM ( SELECT a.baseentityid,
a.team,
a.vaccinedate,
a.vaccine,
a.vaccinesource,
a.num,
a.providerid,
CASE
WHEN a.vaccinesource = 'vaccinatoradministered' THEN dense_rank() OVER (PARTITION BY a.baseentityid, (
CASE
WHEN a.vaccinesource = 'vaccinatoradministered' THEN 1
ELSE 0
END) ORDER BY (CONVERT(VARCHAR(10),a.vaccinedate,111)) )
ELSE 0
END AS visitrank
FROM basequery a
WHERE a.rn = 1
GROUP BY a.baseentityid, a.team, a.vaccinedate, a.vaccine, a.vaccinesource, a.num, a.providerid
ORDER BY a.baseentityid, a.num) aa;
I get this error with my query, but I can't figure out what is wrong with it:
Query-specified return tuple has 135 columns but crosstab returns 295.
And here's my query: (The part highlighted in bold returns same number of rows when run separately in pgAdmin.)
SELECT X.*, pi.productcode, pi.productitemdesc, pi.retailsalesprice, cat.productcategorydesc FROM (
SELECT * FROM crosstab (
'SELECT a.productitem AS productitemid, l.locationcode, (CASE WHEN SUM(a.netamount) IS NOT NULL THEN SUM(a.netamount) ELSE 0 END) || ''#'' || (CASE WHEN SUM(a.quantity) IS NOT NULL THEN SUM(a.quantity) ELSE 0 END) AS sales_qty FROM invoiceitem a INNER JOIN invoiceinfo b ON a.invoice = b.invoiceid INNER JOIN locationinfo l ON b.location = l.locationid WHERE b.status !=2 AND l.locationtype = 1 AND l.status = 1 AND TO_CHAR (b.invoicedate, ''YYYY-MM-DD'')>=''2018-03-01'' AND TO_CHAR (b.invoicedate, ''YYYY-MM-DD'')<=''2018-03-03'' GROUP BY a.productitem, l.locationcode ORDER BY a.productitem',
'SELECT l.locationcode FROM locationinfo l INNER JOIN invoiceinfo b ON b.location = l.locationid
WHERE b.status !=2 AND l.locationtype = 1 AND l.status = 1 AND TO_CHAR (b.invoicedate, ''YYYY-MM-DD'')>=''2018-03-01'' AND TO_CHAR (b.invoicedate, ''YYYY-MM-DD'')<=''2018-03-03'' GROUP BY l.locationcode order by l.locationcode')
AS (productitemid int, "0007" text,"BE101" text,"BE1013" text,"BE1014" text,"BE102" text,"BE103" text,"BE1034" text,"BE104" text,"BE1040" text,"BE1043" text,"BE1044" text,"BE1045" text,"BE1046" text,"BE105" text,"BE106" text,"BE107" text,"BE108" text,"BE109" text,"BE110" text,"BE111" text,"BE112" text,"BE123" text,"BE1265" text,"BE1266" text,"BE1271" text,"BE1272" text,"BE1273" text,"BE1274" text,"BE1279" text,"BE1280" text,"BE1281" text,"BE1282" text,"BE1351" text,"BE1400" text,"BE1401" text,"BE1404" text,"BE141" text,"BE142" text,"BE193" text,"BE194" text,"BE2125" text,"BE2126" text,"BE2127" text,"BE2128" text,"BE3001" text,"BE3002" text,"BE3005" text,"BE3006" text,"BE3009" text,"BE3010" text,"BE3031" text,"BE3032" text,"BE3121" text,"BE3122" text,"BE3123" text,"BE3124" text,"BE3127" text,"BE3128" text,"BE3131" text,"BE3132" text,"BE3203" text,"BE3204" text,"BE325" text,"BE3253" text,"BE3254" text,"BE326" text,"BE332" text,"BE3503" text,"BE3504" text,"BE355" text,"BE356" text,"BE365" text,"BE366" text,"BE381" text,"BE382" text,"BE383" text,"BE384" text,"BE400" text,"BE401" text,"BE402" text,"BE403" text,"BE405" text,"BE406" text,"BE408" text,"BE409" text,"BE411" text,"BE412" text,"BE4311" text,"BE4316" text,"BE4401" text,"BE4402" text,"BE4521" text,"BE4522" text,"BE4551" text,"BE4552" text,"BE470" text,"BE473" text,"BE475" text,"BE481" text,"BE482" text,"BE601" text,"BE604" text,"BE609" text,"BE610" text,"BE7040" text,"BE7043" text,"BE7045" text,"BE7046" text,"BE7048" text,"BE7049" text,"BE708" text,"BE7111" text,"BE7112" text,"BE7127" text,"BE7128" text,"BE7217" text,"BE7218" text,"BE7307" text,"BE7308" text,"BE7351" text,"BE7352" text,"BE801" text,"BE802" text,"BE803" text,"BE804" text,"BE831" text,"BE832" text,"BE860" text,"BE861" text,"BE862" text,"BE863" text,"BE865" text,"BE981" text,"BE982" text
)) X
LEFT JOIN productitem pi ON X.productitemid = pi.productitemid
LEFT JOIN productcategory cat ON pi.productcategory = cat.productcategoryid
The bold part of
productitemid int, "0007" text,"BE101" text,"BE1013" text,"BE1014" text,"BE102" text,"BE103" text,"BE1034" text,"BE104" text,"BE1040" text,"BE1043" text,"BE1044" text,"BE1045" text,"BE1046" text,"BE105" text,"BE106" text,"BE107" text,"BE108" text,"BE109" text,"BE110" text,"BE111" text,"BE112" text,"BE123" text,"BE1265" text,"BE1266" text,"BE1271" text,"BE1272" text,"BE1273" text,"BE1274" text,"BE1279" text,"BE1280" text,"BE1281" text,"BE1282" text,"BE1351" text,"BE1400" text,"BE1401" text,"BE1404" text,"BE141" text,"BE142" text,"BE193" text,"BE194" text,"BE2125" text,"BE2126" text,"BE2127" text,"BE2128" text,"BE3001" text,"BE3002" text,"BE3005" text,"BE3006" text,"BE3009" text,"BE3010" text,"BE3031" text,"BE3032" text,"BE3121" text,"BE3122" text,"BE3123" text,"BE3124" text,"BE3127" text,"BE3128" text,"BE3131" text,"BE3132" text,"BE3203" text,"BE3204" text,"BE325" text,"BE3253" text,"BE3254" text,"BE326" text,"BE332" text,"BE3503" text,"BE3504" text,"BE355" text,"BE356" text,"BE365" text,"BE366" text,"BE381" text,"BE382" text,"BE383" text,"BE384" text,"BE400" text,"BE401" text,"BE402" text,"BE403" text,"BE405" text,"BE406" text,"BE408" text,"BE409" text,"BE411" text,"BE412" text,"BE4311" text,"BE4316" text,"BE4401" text,"BE4402" text,"BE4521" text,"BE4522" text,"BE4551" text,"BE4552" text,"BE470" text,"BE473" text,"BE475" text,"BE481" text,"BE482" text,"BE601" text,"BE604" text,"BE609" text,"BE610" text,"BE7040" text,"BE7043" text,"BE7045" text,"BE7046" text,"BE7048" text,"BE7049" text,"BE708" text,"BE7111" text,"BE7112" text,"BE7127" text,"BE7128" text,"BE7217" text,"BE7218" text,"BE7307" text,"BE7308" text,"BE7351" text,"BE7352" text,"BE801" text,"BE802" text,"BE803" text,"BE804" text,"BE831" text,"BE832" text,"BE860" text,"BE861" text,"BE862" text,"BE863" text,"BE865" text,"BE981" text,"BE982" text
AND
SELECT l.locationcode FROM locationinfo l INNER JOIN invoiceinfo b ON b.location = l.locationid
WHERE b.status !=2 AND l.locationtype = 1 AND l.status = 1 AND TO_CHAR (b.invoicedate, ''YYYY-MM-DD'')>=''2018-03-01'' AND TO_CHAR (b.invoicedate, ''YYYY-MM-DD'')<=''2018-03-03'' GROUP BY l.locationcode order by l.locationcode
When run seperately, I get 295 results which is correct. However putting it together in the whole query gets the error.
The manual:
The remaining output columns must have the type of the last column of the source_sql query's result, and there must be exactly as many of them as there are rows in the category_sql query's result.
crosstab(text, text) with a dynamic (!) SELECT query as 2nd parameter is very error prone, since the output column list is static. You should also generate the output column list dynamically. Example:
Dynamic alternative to pivot with CASE and GROUP BY
That aside, the different number of rows returned from the same query, may very well be due to a different timezone setting in the two different sessions.
You have the expression TO_CHAR(b.invoicedate, 'YYYY-MM-DD') in your predicates. If b.invoicedate is type timestamptz the result depends on the timezone setting. Consider:
SET timezone = '+10';
SELECT TO_CHAR(timestamptz '2018-04-07 23:30+0', 'YYYY-MM-DD');
to_char
----------
2018-04-08
SET timezone = '-10';
SELECT TO_CHAR(timestamptz '2018-04-07 23:30+0', 'YYYY-MM-DD');
to_char
----------
2018-04-07
Solution
To remove the dependency on the timezone setting, use absolute values.
to_char() is expensive complication in this place to begin with. Drop that and adjust the predicate.
Provide timestamptz values to match your column. This also allows indexes to be used (if applicable).
Return Table Type from A function in PostgreSQL
Use time zone names (not offsets or abbreviations) to avoid more misunderstandings.
Ignoring timezones altogether in Rails and PostgreSQL
Use dollar-quoting to clean up the quote mess.
Insert text with single quotes in PostgreSQL
I suggest this as 2nd parameter:
$$
SELECT l.locationcode
FROM locationinfo l
JOIN invoiceinfo b ON b.location = l.locationid
WHERE b.status <> 2 AND l.locationtype = 1 AND l.status = 1
AND b.invoicedate >= timestamptz '2018-03-01 Europe/Vienna'
AND b.invoicedate < timestamptz '2018-03-04 Europe/Vienna'
GROUP BY 1
ORDER BY 1
$$
Replace Europe/Vienna in my example with the time zone name defining your dates.
Note 2018-03-04 to include all of 2018-03-03 like you intended.
I have Query which need to be modified like if I pass zone=All then it should display all records else other condition. This query I have to use in SSRS Reports, it works in this condition.
select distinct zone, wardno,deptname,
cybertec_view_requests.statusname,
categoryname,opendate,probdesc
from cybertec_view_requests
left join cybertec_view_requests_comments on
cybertec_view_requests_comments.reqid = cybertec_view_requests.id_
where zone= ? and deptname=? and
opendate between ? and ? and categoryname=?
group by zone,wardno,deptname, cybertec_view_requests.statusname,
categoryname,opendate,probdesc
order by zone,wardno,deptname
try this
Hear #zone is your variable to pass in the Query
SELECT DISTINCT zone, wardno,deptname, cybertec_view_requests.statusname, categoryname,opendate,probdesc
FROM cybertec_view_requests
LEFT JOIN cybertec_view_requests_comments ON cybertec_view_requests_comments.reqid = cybertec_view_requests.id_
WHERE zone= CASE WHEN #zone = 'ALL' THEN zone ELSE #zone END and deptname=? and
opendate between ? and ? and categoryname=?
GROUP BY zone,wardno,deptname, cybertec_view_requests.statusname,
categoryname,opendate,probdesc
ORDER BY zone,wardno,deptname