Return MAX After Selection - select

I very new to SQL Queries and am having issue with Getting MAX of Column Speedo below is my current query
SELECT
tblVehicle.Rego
,tbljob.Speedo
,tbljob.DateEntered
from tblJob
INNER JOIN tblVehicle
on tbljob.Vehicle_ID = tblVehicle.ID
where JobType_ID = 2
order by Rego
Which outputs
Rego Speedo DateEntered
000JKC 147729 2010-05-10 10:56:55.040
000JKC 150145 2010-06-02 13:57:15.470
000JKC 169553 2011-01-06 12:24:09.143
000JKC 155149 2010-07-21 14:58:20.777
000JKC 157882 2010-09-17 16:39:48.480
000JKC 165660 2010-11-29 08:20:39.453
000JKC 164339 2010-11-18 16:19:19.213
000JKC 155149 2010-08-11 06:16:28.180
000RQD 65 2011-11-21 09:27:31.693
000RQD 6978 2012-03-06 15:18:06.987
000RQD 6766 2012-02-24 13:28:47.603
000RQD 12130 2012-08-28 09:29:18.027
000RQD 12145 2012-08-27 14:57:17.330
000RQD 21550 2013-04-15 19:30:30.160
000RQD 23640 2013-05-22 16:16:33.880
Now i would just like the MAX(Speedo) of Each Rego Only.

The MAX() function returns the largest value of the selected column.
SELECT
tblVehicle.Rego
, MAX( tbljob.Speedo )
,tbljob.DateEntered
from tblJob
INNER JOIN tblVehicle
on tbljob.Vehicle_ID = tblVehicle.ID
where JobType_ID = 2
order by Rego

You need to use GROUP BY
SELECT
tblVehicle.Rego
,MAX(tbljob.Speedo) as MaxSpeedo
,MAX(tbljob.DateEntered) as MaxDate
from tblJob
INNER JOIN tblVehicle
on tbljob.Vehicle_ID = tblVehicle.ID
where JobType_ID = 2
order by Rego
GROUP BY Rego
Note: This may not achieve the result you want if the Speedo is wound back, and the last date does not have the maximum for Speedo. In that scenario you will see the maximum speedo, and the maximum date, but they are coming from different rows.

Related

Query returning different number of rows, results in crosstab error

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.

Getting the nearest instances from the past and the future

I've got a table that contains appointment records, and the user selects a date range (begin_date, end_date). I would like to get the appointment that falls in this date range, as well as the closest instances in the past and future that fall outside of this date range (aka, the previous occurrence and the next occurrence).
I think the best way to approach this is using CTEs and self joins, but I'm open to another strategy. This is my current query:
WITH present AS
(SELECT appt.ewssubject, appt.ewsstart::DATE, appt.ewsend::DATE
FROM appointment appt
WHERE (appt.ewsstart, appt.ewsend) OVERLAPS (begin_date::DATE, end_date::DATE))
SELECT
present.ewssubject, present.ewsstart, present.ewsend,
past.ewssubject AS pastsubject, past.ewsstart::DATE AS paststart,past.ewsend::DATE AS pastend,
future.ewssubject AS futuresubject, future.ewsstart::date AS futurestart, future.ewsend::date AS futureend
FROM present
LEFT JOIN appointment AS past USING (ewssubject)
LEFT JOIN appointment AS future USING (ewssubject)
WHERE
present.ewssubject = past.ewssubject AND
present.ewssubject = future.ewssubject AND
past.ewsend < present.ewsstart AND
future.ewsstart > present.ewsend
ORDER BY present.ewsstart ASC
I'm getting a huge list of appointments, and there are a lot of repeats -- like so:
subject start end last_start last_end next_start next_end
DINNER 2015-09-18 2015-09 18 2015-09-17 2015-09-17 2015-09-19 2015-09-19
DINNER 2015-09-18 2015-09 18 2015-09-17 2015-09-17 2015-09-19 2015-09-19
... // more repeats! :(
All I want to do is reduce the number of duplicates, like this format:
subject start end last_start last_end next_start next_end
DINNER 2015-09-18 2015-09-18 2015-09-17 2015-09-17 2015-09-19 2015-09-19
DINNER 2015-09-21 2015-09-21 2015-09-18 2015-09-18 2015-10-02 2015-10-02
... // and so on
n.b. An appointment can span multiple days.
How can I fix my query? Or is there another one I can write?
You did not enter details about your data so I'm not sure whether this is a good idea, but you can probably use window functions:
select
ewssubject, ewsstart, ewsend,
lag(ewsstart) over (partition by ewssubject order by ewstart) prior_start,
lag(ewsend) over (partition by ewssubject order by ewstart) prior_end,
lead(ewsstart) over (partition by ewssubject order by ewstart) next_start,
lead(ewsend) over (partition by ewssubject order by ewstart) next_end
from appointment
order by ewstart;

If else Condition in PostgreSql

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

How to select first and last records between certain date parameters?

I need a Query to extract the first instance and last instance only between date parameters.
I have a Table recording financial information with financialyearenddate field linked to Company table via companyID. Each company is also linked to programme table and can have multiple programmes. I have a report to pull the financials for each company
on certain programme which I have adjusted to pull only the first and last instance (using MIN & MAX) however I need the first instance.
after a certain date parameter and the last instance before a certain date parameter.
Example: Company ABloggs has financials for 1999,2000,2001,2004,2006,2007,2009 but the programme ran from 2001 to 2007 so I only want
the first financial record and last financial record between those years i.e. 2001 & 2007 records. Any help appreciated.
At the moment I am using 2 queries as I needed the data in a hurry but I need it in 1 query and only where financial year end dates are between parameters and only where there are minimum of 2 GVA records for a company.
Query1:
SELECT
gva.ccx_companyname,
gva.ccx_depreciation,
gva.ccx_exportturnover,
gva.ccx_financialyearenddate,
gva.ccx_netprofitbeforetax,
gva.ccx_totalturnover,
gva.ccx_totalwages,
gva.ccx_statusname,
gva.ccx_status,
gva.ccx_company,
gva.ccx_totalwages + gva.ccx_netprofitbeforetax + gva.ccx_depreciation AS GVA,
gva.ccx_nofulltimeequivalentemployees
FROM
(
SELECT
ccx_companyname,
MAX(ccx_financialyearenddate) AS LatestDate
FROM Filteredccx_gva AS Filteredccx_gva_1
GROUP BY ccx_companyname
) AS min_1
INNER JOIN Filteredccx_gva AS gva
ON min_1.ccx_companyname = gva.ccx_companyname AND
min_1.LatestDate = gva.ccx_financialyearenddate
WHERE (gva.ccx_status = ACTUAL)
Query2:
SELECT
gva.ccx_companyname,
gva.ccx_depreciation,
gva.ccx_exportturnover,
gva.ccx_financialyearenddate,
gva.ccx_netprofitbeforetax,
gva.ccx_totalturnover,
gva.ccx_totalwages,
gva.ccx_statusname,
gva.ccx_status,
gva.ccx_company,
gva.ccx_totalwages + gva.ccx_netprofitbeforetax + gva.ccx_depreciation AS GVA,
gva.ccx_nofulltimeequivalentemployees
FROM
(
SELECT
ccx_companyname,
MIN(ccx_financialyearenddate) AS FirstDate
FROM Filteredccx_gva AS Filteredccx_gva_1
GROUP BY ccx_companyname
) AS MAX_1
INNER JOIN Filteredccx_gva AS gva
ON MAX_1.ccx_companyname = gva.ccx_companyname AND
MAX_1.FirstDate = gva.ccx_financialyearenddate
WHERE (gva.ccx_status = ACTUAL)
Can't you just add a where clause using the first and last date parameters. Something like this:
SELECT <companyId>, MIN(<date>), MAX(<date>)
FROM <table>
WHERE <date> BETWEEN #firstDate AND #lastDate
GROUP BY <companyId>
declare #programme table (ccx_companyname varchar(max), start_year int, end_year int);
insert #programme values
('ABloggs', 2001, 2007);
declare #companies table (ccx_companyname varchar(max), ccx_financialyearenddate int);
insert #companies values
('ABloggs', 1999)
,('ABloggs', 2000)
,('ABloggs', 2001)
,('ABloggs', 2004)
,('ABloggs', 2006)
,('ABloggs', 2007)
,('ABloggs', 2009);
select c.ccx_companyname, min(ccx_financialyearenddate), max(ccx_financialyearenddate)
from #companies c
join #programme p on c.ccx_companyname = p.ccx_companyname
where c.ccx_financialyearenddate >= p.start_year and c.ccx_financialyearenddate <= p.end_year
group by c.ccx_companyname
having count(*) > 1;
You can combine your two original queries into a single query by including the MIN and MAX aggregates in the same GROUP BY query of the virtual table. Also including COUNT() and HAVING COUNT() > 1 ensures company must have at least 2 dates. So query should look like:
SELECT
gva.ccx_companyname,
gva.ccx_depreciation,
gva.ccx_exportturnover,
gva.ccx_financialyearenddate,
gva.ccx_netprofitbeforetax,
gva.ccx_totalturnover,
gva.ccx_totalwages,
gva.ccx_statusname,
gva.ccx_status,
gva.ccx_company,
gva.ccx_totalwages + gva.ccx_netprofitbeforetax + gva.ccx_depreciation AS GVA,
gva.ccx_nofulltimeequivalentemployees
FROM
(SELECT
ccx_companyname,
ccx_status,
MIN(ccx_financialyearenddate) AS FirstDate,
MAX(ccx_financialyearenddate) AS LastDate,
COUNT(*) AS NumDates
FROM Filteredccx_gva AS Filteredccx_gva_1
WHERE (ccx_status = ACTUAL)
GROUP BY ccx_companyname, ccx_status
HAVING COUNT(*) > 1
) AS MinMax
INNER JOIN Filteredccx_gva AS gva
ON MinMax.ccx_companyname = gva.ccx_companyname AND
(MinMax.FirstDate = gva.ccx_financialyearenddate OR
MinMax.LastDate = gva.ccx_financialyearenddate)
WHERE (gva.ccx_status = MinMax.ccx_status)
ORDER BY gva.ccx_companyname, gva.ccx_financialyearenddate

multiplication in group by , dyslexia

Now this is a simple insert query with one subquery and it's working perfectly:
INSERT INTO CSolutions..Report2
SELECT Nov.Chain, CG.Grouping, reg.code as regcode,reg.pname,reg.fname,reg.sname, SUM(NS.Currency) as sumeur , sum(ns2.kpl) as sumkpl,0,0,0,0
FROM CSolutions..NovSales NS,CSolutions..NSaleskpl NS2, CSolutions..NovCGroup CG, sales..reg_eng reg,
(SELECT DISTINCT P.Code, Nov.Chain
FROM Register..Pcy P
INNER JOIN Register..TCustomer TC ON (P.Code = TC.PCode)
INNER JOIN CSolutions..Novies2 Nov ON (TC.Code = Nov.TCode)
) AS Nov
WHERE NS.SpCode = CG.SpCode and ns.spcode = ns2.spcode AND Ns.PCode = Nov.Code
and ns.spcode = reg.code
and ns.pcode = ns2.pcode
**and NS.SalesMonth = '201205'
and NS2.SalesMonth = '201205'**
GROUP BY Nov.Chain, CG.Grouping , reg.code,reg.pname,reg.fname,reg.sname
This is derivate of the same query, but it's not working correctly:
INSERT INTO CSolutions..Report2
SELECT Nov.Chain, CG.Grouping, reg.code as regcode,reg.pname,reg.fname,reg.sname, SUM(NS.Currency) as sumeur , sum(ns2.kpl) as sumkpl,0,0,0,0
FROM CSolutions..NovSales NS,CSolutions..NSaleskpl NS2, CSolutions..NovCGroup CG, sales..reg_eng reg,
(SELECT DISTINCT P.Code, Nov.Chain
FROM Register..Pcy P
INNER JOIN Register..TCustomer TC ON (P.Code = TC.PCode)
INNER JOIN CSolutions..Novies2 Nov ON (TC.Code = Nov.TCode)
) AS Nov
WHERE NS.SpCode = CG.SpCode and ns.spcode = ns2.spcode AND Ns.PCode = Nov.Code
and ns.spcode = reg.code
and ns.pcode = ns2.pcode
**and NS.SalesMonth between '201201' and '201205'
and NS2.SalesMonth between '201201' and '201205'**
GROUP BY Nov.Chain, CG.Grouping , reg.code,reg.pname,reg.fname,reg.sname
This will give 5 times the 5 month sum amount,
I am a dyslexic and i have hard time to spot the error, I hope someone can help me ?? :)
There is no join on the salesmonth in CSolutions..NovSales and CSolutions..NSaleskpl NS2. In the frist query this does not matter because you are only looking at one salesmonth. In the second query I presume there are multiple salesmonth's as you are selecting a range of value from each table. You are getting a cross join because of this of salesmonth's because of this.