Why i get mysql result column value dismatch - mysql

msyql query
SELECT id,student_user_id,MIN(start_time) FROM appoint_course
WHERE student_user_id IN(
931,2034,2068,2111,2115,2173,2181,2285,2500,2505,2507,
2518,2594,2596,2600,2608,2637,2652,2654
)
AND course_type=3 and disabled=0 GROUP BY student_user_id;
result
[query result]
+-------+-----------------+-----------------+
| id | student_user_id | MIN(start_time) |
+-------+-----------------+-----------------+
| 8356 | 931 | 1500351000 |
| 9205 | 2034 | 1501733400 |
| 9246 | 2068 | 1501649100 |
| 9755 | 2111 | 1502943000 |
| 9585 | 2115 | 1502595300 |
| 10820 | 2173 | 1503545700 |
| 9594 | 2181 | 1502852400 |
| 10324 | 2285 | 1502852400 |
| 11204 | 2500 | 1504839600 |
| 11152 | 2507 | 1504064100 |
| 12480 | 2594 | 1505707800 |
| 11521 | 2608 | 1504494000 |
| 11818 | 2652 | 1504753200 |
+-------+-----------------+-----------------+
but right start time is:
id: 9594
start_time: 1503284400
9594 right start_time is 1503284400 not 1502852400.In fact 1502852400 is a record of 9597
I do not know why.

In any other database your query would return an error, because id is not in the group by. The correct query is:
SELECT student_user_id, MIN(start_time)
FROM appoint_course
WHERE student_user_id IN (931,2034,2068,2111,2115,2173,2181,2285,2500,2505,2507,2518,2594,2596,2600,2608,2637,2652,2654) AND
course_type = 3 and disabled = 0
GROUP BY student_user_id;
In your case, adding a simple MIN(id) to the SELECT might work, assuming that ids increase with the start time.
More generally, you appear to want:
SELECT ac.*
FROM appoint_course ac
WHERE ac.student_user_id IN (931,2034,2068,2111,2115,2173,2181,2285,2500,2505,2507,2518,2594,2596,2600,2608,2637,2652,2654) AND
ac.course_type = 3 AND ac.disabled = 0 AND
ac.start_time = (SELECT MIN(ac2.start_time)
FROM appoint_course ac2
WHERE ac2.student_user_id = ac.student_user_id AND
ac2.course_type = ac.course_type AND
ac2.disabled = ac.disabled
);
No GROUP BY is necessary.
I should add that there is a MySQL hack that often works:
SELECT student_user_id, MIN(start_time),
SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY start_time), ',', 1) as id_at_min_start_time
FROM appoint_course
WHERE student_user_id IN (931,2034,2068,2111,2115,2173,2181,2285,2500,2505,2507,2518,2594,2596,2600,2608,2637,2652,2654) AND
course_type = 3 and disabled = 0
GROUP BY student_user_id;
This uses string manipulations and the GROUP_CONCAT() can overflow internal buffer sizes.

Related

How to group by and sum with sub query

i use this query below to get the data
SELECT
tsi.shipping_service,
tsi.shipment_amount as shipping_cost,
(
SELECT sum(shipment_cost) FROM tabPacking Slip packages shadow sps
WHERE parent =
(SELECT name FROM tabPacking Slip pslip
WHERE pslip.purchase_order = tsi.po_no LIMIT 1
)
GROUP BY tsi.shipping_service
)
as cobb_charge
FROM tabSales Invoice as tsi;
OUTPUT
+-------------------------------------+---------------+-------------+
| shipping_service | shipping_cost | cobb_charge |
+-------------------------------------+---------------+-------------+
| UPS-Ground | 32.150000 | 32.150000 |
| UPS-Ground | 0.000000 | 18.150000 |
| UPS-Ground | 53.740000 | 0.000000 |
| UPS-Ground | 20.240000 | 20.240000 |
| UPS-Ground | 14.710000 | 14.710000 |
| UPS-Ground | 18.410000 | 18.410000 |
| UPS-Ground | 21.740000 | 21.740000 |
i need to group this data by shipping service and sum all the cost and charge
If your query produce the result in your output you can try:
select a.shipping_service,
sum(a.shipping_cost),
sum(a.cobb_charge)
from
(
SELECT
tsi.shipping_service,
tsi.shipment_amount as shipping_cost,
(
SELECT sum(shipment_cost) FROM tabPacking Slip packages shadow sps
WHERE parent =
(SELECT name FROM tabPacking Slip pslip
WHERE pslip.purchase_order = tsi.po_no LIMIT 1
)
GROUP BY tsi.shipping_service
)
as cobb_charge
FROM tabSales Invoice as tsi
) as a group by a.shipping_service ;

How come I get a syntax error when using a CTE to update a table?

I have a column (share_2pp) that needs to be updated with a calculated result from the table. This select query produces the column (share_2pp) I would like.
WITH cte
AS (
SELECT recipe
, SUM(meal_nr) AS meal_sum
FROM w03_forecast
GROUP BY recipe
)
SELECT w03_forecast.recipe
, w03_forecast.meal_nr
, meal_sum
, (meal_nr / meal_sum) AS share_2pp
FROM w03_forecast
INNER JOIN cte
ON w03_forecast.recipe = cte.recipe;
+--------+---------+----------+-----------+
| recipe | meal_nr | meal_sum | share_2pp |
+--------+---------+----------+-----------+
| 1 | 3842 | 4593 | 0.8365 |
| 2 | 4284 | 5130 | 0.8351 |
| 3 | 4166 | 4926 | 0.8457 |
| 4 | 2830 | 3382 | 0.8368 |
| 5 | 2495 | 2935 | 0.8501 |
| 1 | 751 | 4593 | 0.1635 |
| 2 | 846 | 5130 | 0.1649 |
| 3 | 760 | 4926 | 0.1543 |
| 4 | 552 | 3382 | 0.1632 |
| 5 | 440 | 2935 | 0.1499 |
+--------+---------+----------+-----------+
However, when I try to update the table I get a syntax error at FROM.
WITH cte
AS (
SELECT recipe
, SUM(meal_nr) AS meal_sum
FROM w03_forecast
GROUP BY recipe
)
UPDATE w03_forecast
SET w03_forecast.share_2pp = (meal_nr / meal_sum)
FROM w03_forecast
INNER JOIN cte
ON w03_forecast.recipe = cte.recipe;
I think you can just use JOIN:
UPDATE w03_forecast f JOIN
(SELECT recipe, SUM(meal_nr) AS meal_sum
FROM w03_forecast
GROUP BY recipe
) r
USING (recipe)
SET f.share_2pp = (meal_nr / meal_sum);
That said, there is no reason to store this in the table. It can easily be calculated on-the-fly using window functions:
select f.*,
(meal_nr / sum(meal_nr) over ()) as share_2pp
from w03_forecast f

Nested JOIN to create custom dynamic columns

I have a table veicoli (vehicles) like this:
-------------------------------
| ID | Modello | Targa |
-------------------------------
| 1 | IVECO | XA123WE |
-------------------------------
| 2 | IVECO | CF556XD |
-------------------------------
| 3 | FIAT | AS332ZZ |
-------------------------------
| 4 | GOLF | GF567YU |
-------------------------------
For each vehicle I have none, one or multiple revisioni_veicolo (revisions) (the one with bigger DateExpiring is the one I need to check if revision is still valid or not based on today date)
-------------------------------------------------------------------
| ID | veicoli_ID | DateExpiring | Pass_Success |
-------------------------------------------------------------------
| 1 | 1 | 2019-07-01 | 1
------------------------------------------------------------------
| 2 | 1 | 2020-10-01 | 0
-------------------------------------------------------------------
| 3 | 2 | 2019-11-25 | 1
-------------------------------------------------------------------
| 4 | 2 | 2018-10-20 | 1
-------------------------------------------------------------------
| 5 | 4 | 2017-10-20 | 1
-------------------------------------------------------------------
Based on my example above (today is 2019-10-29):
Vehicle: ID = 1 has a revision still active (2020-10-01) but not passed (Pass_success = 0)
Vehicle: ID = 2 has a revision still active (2019-11-25) and passed (Pass_success = 1)
Vehicle: ID = 3 has no revision yet
Vehicle: ID = 4 has revision, but no active revision (last expired on 2017-10-20) but the last one passed the check (Pass_success = 1)
What I need is to have 3 new custom columns created dynamically on my query result:
-------------------------------------------------------------------------------------------
| ID | Modello | Targa | RevisionPresent | RevisionStillActive | LastRevisionPassed |
-------------------------------------------------------------------------------------------
| 1 | IVECO | XA123WE | true | true | false
-------------------------------------------------------------------------------------------
| 2 | IVECO | CF556XD | true | true | true
-------------------------------------------------------------------------------------------
| 3 | FIAT | AS332ZZ | false | false | false
-------------------------------------------------------------------------------------------
| 4 | GOLF | GF567YU | true | false | true
-------------------------------------------------------------------------------------------
I tried to start with my old post: MYSQL INNER JOIN to get 3 types of result
But I'm very confused using nested JOIN
I tried starting a fiddle but i'm stuck on syntax error: http://sqlfiddle.com/#!9/3c70bf/2
You need a LEFT JOIN of the tables and conditional aggregation:
select v.ID, v.Modello, v.Targa,
max(r.DataScadenzaRevisione is not null) RevisionPresent,
coalesce(max(r.DataScadenzaRevisione >= current_date()), 0) RevisionStillActive,
max(case when r.DataScadenzaRevisione = g.maxdate then r.EsitoPositivo else 0 end) LastRevisionPassed
from veicoli v
left join revisioni_veicolo r on r.veicoli_ID = v.id
left join (
select veicoli_id, max(DataScadenzaRevisione) maxdate
from revisioni_veicolo
group by veicoli_id
) g on g.veicoli_ID = v.id
group by v.ID, v.Modello, v.Targa
See the demo.
Results:
| ID | Modello | Targa | RevisionPresent | RevisionStillActive | LastRevisionPassed |
| --- | ------- | ------- | --------------- | ------------------- | ------------------ |
| 1 | IVECO | XA123WE | 1 | 1 | 0 |
| 2 | IVECO | CF556XD | 1 | 1 | 1 |
| 3 | FIAT | AS332ZZ | 0 | 0 | 0 |
| 4 | GOLF | GF567YU | 1 | 0 | 1 |
...
LEFT JOIN (SELECT a.veicoli_ID, a.EsitoPositivo AS StatoUltimaRevisione,
a.DataScadenzaRevisione FROM revisioni_veicolo) a
...
There's two things wrong with this.
The alias a is defined for this subquery, so you can't reference it inside the subquery. But you don't need to qualify the columns in this subquery anyway - you didn't do this in other subqueries, so I'm not sure why you did it in this case.
You don't have any join condition for this join. MySQL is a little bit inconsistent about when join conditions are required. But in this case, you need one.
After I tested the query with these two corrections, it works.
Basically you just need to look at the last revision of each vehicule to produce that resultset.
You can do the filtering with a correlated subquery:
select
v.ID,
v.Modello,
v.Targa,
(DataScadenzaRevisione >= now()) RevisionPresent,
(DataScadenzaRevisione >= now() and EsitoPositivo = 1) RevisionStillActive,
(EsitoPositivo = 1) LastRevisionPassed
from
veicoli v
left join revisioni_veicolo r
on r.veicoli_ID = v.ID
and r.DataScadenzaRevisione = (
select max(DataScadenzaRevisione)
from revisioni_veicolo r1
where r1.veicoli_ID = v.ID
)
You can check the results with your sample data in this db fiddle.
Or you can use a window function (this requires MySQL 8.0):
select
v.ID,
v.Modello,
v.Targa,
(DataScadenzaRevisione >= now()) RevisionPresent,
(DataScadenzaRevisione >= now() and EsitoPositivo = 1) RevisionStillActive,
(EsitoPositivo = 1) LastRevisionPassed
from (
select
v.*,
r.*,
row_number() over(partition by ID order by r.DataScadenzaRevisione desc) rn
from veicoli v
left join revisioni_veicolo r on r.veicoli_ID = v.ID
) where coaelesce(rn, 1) = 1

Combine Two Queries with Separate Indexes

I have two queries that pull data from two different tables, but I need them to pull in the same report. I have a shared key between them, and the first table has one entry that corresponds to many entries in the second table.
My first query:
SELECT Proposal_ID,
substr(Proposal_Name, 1, 3) AS Prefix,
substr(Proposal_Name, 4, 6) AS `Number`,
Institution,
CollegeCode,
DepartmentCode,
Proposer_FirstName,
Proposer_LastName
FROM proposals.proposal
WHERE Institution = 'T';
Sample Data:
+----+--------+--------+-------+----------+----------+-----------+----------+
| ID | Prefix | Number | Inst. | CollCode | DeptCode | FirstName | LastName |
+----+--------+--------+-------+----------+----------+-----------+----------+
| 18 | SYP | 4675 | T | AS | SOC | Linda | McGaff |
+----+--------+--------+-------+----------+----------+-----------+----------+
| 20 | GEO | 4340 | T | AS | SGS | Teddy | Graham |
+----+--------+--------+-------+----------+----------+-----------+----------+
My second query:
SELECT Parent_Proposal,
SUBSTRING_INDEX(GROUP_CONCAT(`status`.`Status_Code` ORDER BY `status`.`Status_Time` DESC), ',', 1) AS status_code,
SUBSTRING_INDEX(GROUP_CONCAT(`status`.`Status_Time` ORDER BY `status`.`Status_Time` DESC), ',', 1) AS status_timestamp
FROM proposals.`status`
GROUP BY `status`.Parent_Proposal
Sample Data:
+-----------------+-------------+----------------------+
| Parent_Proposal | Status_Code | Status_Time |
+-----------------+-------------+----------------------+
| 18 | 40 | 2016-11-09 06:30:35 |
+-----------------+-------------+----------------------+
| 20 | 11 | 2017-03-20 10:26:31 |
+-----------------+-------------+----------------------+
I basically need to pull the most recent Status_Code and Status_Timestamp based on the Status_Timestamp and then relate that to the first table with the Parent_Proposal column.
Is there a way to group a subset of results without grouping all of the data together?
Expected Result:
+----+--------+--------+-------+----------+----------+-------+--------+-------------+----------------------+
| ID | Prefix | Number | Inst. | CollCode | DeptCode | FName | LName | Status_Code | Status_Time |
+----+--------+--------+-------+----------+----------+-------+--------+-------------+----------------------+
| 18 | SYP | 4675 | T | AS | SOC | Linda | McGaff | 40 | 2016-11-09 06:30:35 |
+----+--------+--------+-------+----------+----------+-------+--------+-------------+----------------------+
| 20 | 11 | GEO | 4340 | AS | SGS | Teddy | Graham | 11 | 2017-03-20 10:26:31 |
+----+--------+--------+-------+----------+----------+-------+--------+-------------+----------------------+
Thanks for any help and insight!
I think you want this. Just join your two tables together, and then do an additional join to a subquery on the status table to find the latest record for each parent proposal.
SELECT
p.Proposal_ID,
SUBSTR(p.Proposal_Name, 1, 3) AS Prefix,
SUBSTR(p.Proposal_Name, 4, 6) AS Number,
p.Institution,
p.CollegeCode,
p.DepartmentCode,
p.Proposer_FirstName,
p.Proposer_LastName,
s1.Status_Code,
s1.Status_Time
FROM proposals.proposal p
LEFT JOIN proposals.status s1
ON p.ID = s1.Parent_Proposal
INNER JOIN
(
SELECT Parent_Proposal, MAX(Status_Time) AS Max_Status_Time
FROM proposals.status
GROUP BY Parent_Proposal
) s2
ON s1.Parent_Proposal = s2.Parent_Proposal AND s1.Status_Time = s2.Max_Status_Time
WHERE
p.Institution = 'T';

MySQL : Update Table upon certain conditions

I have 2 tables , master and current table( refreshed very hr).
Both the table shave same structure:
Chk | description |state | date
I need to update / append ( add the new row ) into the master table if :
1) rows that have new IDs or
2) if a particular variable ( 'state' in this case) has changed. I tried to do it using below without success :
INSERT into AGILE_TICKETS_DLY
SELECT * FROM CURR_AGILE_TICKETS curr
WHERE EXISTS (SELECT * FROM AGILE_TICKETS_DLY mstr
WHERE (curr.chk != mstr.chk) OR ( curr.chk = mstr.chk and
mstr.state != curr.state))
Any pointers on how to achieve this ?
You can try this pair of queries:
-- insert new rows
insert into agile_tickets_dly
select * from curr_agile_tickets
where chk not in (select chk from agile_tickets_dly);
-- update updated rows
update agile_tickets_dly x
join
(
select b.chk chk,b.description description,b.state state,b.date date
from agile_tickets_dly a, curr_agile_tickets b
where
a.chk=b.chk and
(a.description != b.description or a.state != b.state or a.date != b.date)
) y
on x.chk=y.chk
set x.description = y.description, x.state= y.state, x.date = y.date;
Illustration:
select * from agile_tickets_dly;
+------+-------------+---------+------------+
| chk | description | state | date |
+------+-------------+---------+------------+
| 0 | desc-0 | state-1 | 01-01-2017 |
| 1 | desc-1 | state-1 | 01-01-2018 |
| 2 | desc-2 | state-2 | 01-02-2018 |
| 3 | desc-3 | state-3 | 01-03-2018 |
+------+-------------+---------+------------+
-- one new row with chk=4, three updated rows with chk=1,2,3
select * from curr_agile_tickets;
+------+----------------+-----------------+----------------+
| chk | description | state | date |
+------+----------------+-----------------+----------------+
| 0 | desc-0 | state-1 | 01-01-2017 |
| 1 | desc-1 | state-1 | date-1-updated |
| 2 | desc-2-updated | state-2 | 01-02-2018 |
| 3 | desc-3 | state-3-updated | 01-03-2018 |
| 4 | desc-4 | state-4 | 01-04-2018 |
+------+----------------+-----------------+----------------+
-- after executing the two queries
select * from agile_tickets_dly;
+------+----------------+-----------------+----------------+
| chk | description | state | date |
+------+----------------+-----------------+----------------+
| 0 | desc-0 | state-1 | 01-01-2017 |
| 1 | desc-1 | state-1 | date-1-updated |
| 2 | desc-2-updated | state-2 | 01-02-2018 |
| 3 | desc-3 | state-3-updated | 01-03-2018 |
| 4 | desc-4 | state-4 | 01-04-2018 |
+------+----------------+-----------------+----------------+
I tried to do this in 2 separate steps:
1) First I append all new rows with IDs : this worked
INSERT into AGILE_TICKETS_DLY
SELECT * FROM CURR_AGILE_TICKETS curr
WHERE not EXISTS (SELECT * FROM AGILE_TICKETS_DLY mstr
WHERE (curr.chk = mstr.chk));
But then, I tried to do below got an error
2) Then replace the 'State' variable with new value:
INSERT into AGILE_TICKETS_DLY_1 (state)
SELECT state
from CURR_AGILE_TICKETS_1 curr
where exists ( select * from AGILE_TICKETS_DLY_1 mstr where curr.chk =
mstr.chk);
But this gives me an error :
SQL Error (1364) : Field 'chk' doesn't have a default value.
What does that mean ?