MySQL - Union or join? - mysql

I'm trying to collect statistic data in one SQL query for the convenience of having the date sorted automatically in a union. It is really only one table but I want to count different cases of data.
The table I have looks something like this:
ID In Wanted
441 2011-03-14 0
439 2011-03-14 1
442 2011-03-14 0
428 2011-03-13 1
431 2011-03-13 1
425 2011-03-11 0
423 2011-03-11 1
420 2011-03-09 1
I get close to the desired result with this query:
SELECT * FROM
(
(SELECT date(In) n, count(date(In)) cntw, null cntl FROM items i WHERE Wanted=1 group by date(In))
union all
(SELECT date(In) n, null cntw, count(date(In)) cntl FROM items i WHERE Wanted=0 group by date(In))
) Serie
Order by n DESC
But close isn't close enough :D The result i get is this:
n cntw cntl
2011-03-14 null 2
2011-03-14 1 null
2011-03-13 2 null
2011-03-11 null 1
2011-03-11 1 null
2011-03-09 1 null
What I want is to "blend" the results on the same line, by date:
n cntw cntl
2011-03-14 1 2
2011-03-13 2 null
2011-03-11 1 1
2011-03-09 1 null
As you can see there is only ONE row for each date.
Actually the most perfect result would be to even have the missing dates in there too:
n cntw cntl
2011-03-14 1 2
2011-03-13 2 null
2011-03-12 null null
2011-03-11 1 1
2011-03-10 null null
2011-03-09 1 null
...but I guess this isn't possible.
Thank you!

select date(In) as n,
sum(case when wanted = 1 then 1 else 0 end) as cntw,
sum(case when wanted = 0 then 1 else 0 end) as cntl
from items
group by date(In)
order by n desc

You'd use a LEFT JOIN using your n field to get the dates where you have stuff... Then you'd UNION this with a query that gives you the lines where there's nothing (the info you give above doesn't allow me to help in what query this would be :D).

You want to join them, I think this will work
SELECT * FROM
(SELECT date(In) n, count(date(In)) cntw, null cntl FROM items i WHERE Wanted=1 group by date(In)) as a
LEFT JOIN
(SELECT date(In) n, null cntw, count(date(In)) cntl FROM items i WHERE Wanted=0 group by date(In)) as b
ON a.n = b.n
Order by n DESC
But I think this can be done in a single query, like this perhaps?
CREATE TABLE #tmpFoo (
SomeDate datetime,
Wanted bit
)
INSERT INTO #tmpFoo VALUES ('2011-03-11', 0)
INSERT INTO #tmpFoo VALUES ('2011-03-11', 1)
INSERT INTO #tmpFoo VALUES ('2011-03-12', 0)
INSERT INTO #tmpFoo VALUES ('2011-03-12', 1)
INSERT INTO #tmpFoo VALUES ('2011-03-14', 0)
SELECT SomeDate n,
count(NULLIF(Wanted,0)) cntw,
count(NULLIF(Wanted,1)) cntl
FROM #tmpFoo i
GROUP BY SomeDate

Related

How to Combine multiple rows to single row based on a column in MySQL or Hive

I need to generate average sales per Title between year 2019 to 2021. There are 2 input tables:
Title Table
Title_id Title_type Price_per
1 tv 10
2 book 50
3 cd 20
Transactions table(trans)
tran_id Title_id Qty year
1 3 2 2019
2 1 1 2019
3 3 5 2020
4 3 3 2020
5 1 10 2021
The expected result should generate below columns:
Title_id|Avg_sales_2019|Avg_sales_2020|Avg_sales_2021
title_id avg_sales_2019 avg_sales_2020 avg_sales_2021
1 10.0 NULL 100.0
3 40.0 80.0 NULL
I used below query, but it does not generate the expected output
select a.title_id,
case when a.year=2019 then avg end as Avg_sales_2019,
case when a.year=2020 then avg end as Avg_sales_2020,
case when a.year=2021 then avg end as Avg_sales_2021
from (Select t.title_id, x.year, AVG(t.Price_per*x.Qty) as avg
from title t join trans x on t.title_id=x.title_id
group by t.title_id,x.year) a;
title_id avg_sales_2019 avg_sales_2020 avg_sales_2021
1 10.0 NULL NULL
1 NULL NULL 100.0
3 40.0 NULL NULL
3 NULL 80.0 NULL
How to combine the rows for a particular title_id to get the expected result
Note: I am running the query in Hive
Use conditional aggregation:
SELECT
t.title_id,
AVG(CASE WHEN x.year = 2019
THEN t.Price_per * x.Qty ELSE 0 END) AS avg_sales_2019,
AVG(CASE WHEN x.year = 2020
THEN t.Price_per * x.Qty ELSE 0 END) AS avg_sales_2020,
AVG(CASE WHEN x.year = 2021
THEN t.Price_per * x.Qty ELSE 0 END) AS avg_sales_2021
FROM title t
LEFT JOIN trans x
ON x.title_id = t.title_id
GROUP BY
t.title_id
ORDER BY
t.title_id;

Count several rows as one if the next row also are less then a value

I want to count all rows that are less then 10 in column "value" but if the next rows also have a value less then 10 only count it as 1(as a group).
So in this exampel I would like to get back the number 3.
I use mysql
So id-2 with value(3) < 10 = +1
Id-4,5,6 value < 10 = +1
Id-9 value < 10 = +1
-- id -- value --
|.. 1 ..|.. 11 ...|
|.. 2 ..|... 3 ...|
|.. 3 ..|.. 12 ...|
|.. 4 ..|... 2 ...|
|.. 5 ..|... 1 ...|
|.. 6 ..|... 3 ...|
|.. 7 ..|.. 15 ...|
|.. 8 ..|.. 24 ...|
|.. 9 ..|... 5 ...|
|. 10 ..|.. 15 ...|
The easiest way to do this is with variables. I would do it in a verbose way, by first putting the previous value in and then doing the logic in an outer query:
select count(*)
from (select t.*,
if(#pp := #prev,
if(#prev := value, #pp, #pp)
) as prev_value
from table t cross join
(select #prev := NULL) vars
order by id
) t
where value > 10 and (prev_value is null or prev_value < 10);
The strange syntax for setting the variables is because the expression needs to fit in one expression (MySQL does not guarantee the order of evaluation of expressions in the SELECT). This stashes the current previous value in a new variable, then sets the #prev variable to the current value, and returns the previous value.
SET #LastVal=NULL;
SET #Count=0;
SELECT #Count:=IF(#LastVal IS NULL OR (Val<10 AND Val!=#LastVal) , #Count:=#Count+1, #Count:=#Count) CountIncrementLogic, #LastVal :=Val AssignmentToLastVal FROM Table
WHERE Val<10;
SELECT #Count;
http://sqlfiddle.com/#!9/e0f1e/3
SELECT SUM(IF(t.i=1,1,0))
FROM(
SELECT IF(`value`>= 10, #i:=0, IF( #i=0,#i:=1,#i:=#i+1)) i
FROM table1
ORDER BY id) t
One option is to join the table on itself and lead it by 1 on the join. This only works if the Id's are sequential and there are no missing Id's. If there are missing Id's then each table could be turned into a subquery with the rank function used to join instead.
The following code checks the value and then checks the previous row's value. If the current row is less than 10 and the previous row is not less than 10 then it is counted in the overall total.
http://sqlfiddle.com/#!9/b82fb/22
SELECT
COUNT(CASE WHEN c.IsRowLessThan10 = 1
AND IFNULL(c.IsNextRowLessThan10,0) = 0 THEN 1 END) AS CountTotal
FROM (SELECT
a.Id,
CASE WHEN a.Value < 10 THEN 1 ELSE 0 END AS IsRowLessThan10,
CASE WHEN b.Value < 10 THEN 1 ELSE 0 END as IsNextRowLessThan10
FROM TableName AS a
LEFT JOIN TableName AS b
ON b.Id + 1 = a.Id
) c

Mysql JOIN with extra priority column

I have two days trying to do this query with no luck.
I have two tables 'DEMAND' and 'DEMAND_STATE' (one to many relation). The table DEMAND_STATE have millions entries.
CREATE TABLE DEMAND
(
ID INT NOT NULL,
DESTINY_ID INT NOT NULL
)
CREATE TABLE DEMAND_STATE
(
ID INT NOT NULL,
PRIORITY INT NOT NULL,
QUANTITY DOUBLE NOT NULL,
CASE_ID INT NOT NULL,
DEMAND_ID INT NOT NULL,
PHASE_ID INT NOT NULL
)
The QUANTITY of the DEMAND_STATE is given according to a CASE_ID and PHASE_ID. We have 'N' PHASES in 'M' CASES. Always the same number of Phases in all Cases. We always have a initial Base Quantity called 'BASE CASE' in the Case with CASE_ID = 1.
For example to obtain quantity for Case (id=2) and Case Base (id=1)
select D.*, S.PRIORITY, S.QUANTITY, S.CASE_ID, S.DEMAND_ID, S.PHASE_ID
FROM DEMAND D
join DEMAND_STATE S on (D.ID = S.DEMAND_ID)
WHERE (S.CASE_ID = 2 OR S.CASE_ID = 1)
(paste only for id=8)
ID PRIORITY QUANTITY CASE_ID DEMAND_ID PHASE_ID
8 0 85 1 8 1
8 0 83 1 8 2
8 0 88 1 8 3
8 0 89 1 8 4
8 10 85 2 8 1
8 10 84 2 8 2
8 10 86 2 8 3
8 10 89 2 8 4
We need to obtain for all Demand in 'DEMAND' only the Quantity for Each Phase with MAX priority. The idea is no duplicate DEMAND_STATE data for each new Case creation. Only create new state rows when Demand-Case-Phase is different to Case Base. This is a new project and we accept changes in model for better performance.
I also tried with the MAX calculation. This query over DEMAND_STATE works fine but only obtain data for a concrete DEMAND_ID. Further i think this solution can be so expensive.
SELECT P.ID, P.QUANTITY, P.CASE_ID, P.DEMAND_ID, P.PHASE_ID
FROM DEMAND_STATE P
JOIN (
SELECT PHASE_ID, MAX(PRIORITY) max_priority, S.DEMAND_ID
from DEMAND_STATE S
WHERE S.DEMAND_ID = 1
AND (S.CASE_ID=1 OR S.CASE_ID=2)
GROUP BY S.PHASE_ID
) SUB
ON (SUB.PHASE_ID = P.PHASE_ID AND SUB.max_priority = P.PRIORITY)
WHERE P.DEMAND_ID = 1
GROUP BY P.PHASE_ID
The result:
ID QUANTITY CASE_ID DEMAND_ID PHASE_ID
1 86 1 1 1
2 85 1 1 2
3 81 1 1 3
8 500 2 1 4
This is the result expected:
ID ID PRIORITY QUANTITY CASE_ID PHASE_ID
8 1 0 86 1 1 (data from Case Base id=1 priority 0)
8 2 10 85 1 2 (data from Case Baseid=1 priority 0)
8 3 10 81 1 3 (data from Case Base id=1 priority 0)
8 64 10 500 2 4 (data from Case id=2 priority 10)
thank for help :)
Edit:
Result of Simon proposal:
ID QUANTITY CASE_ID DEMAND_ID PHASE_ID
1 86 1 1 1
2 85 1 1 2
3 81 1 1 3
4 84 1 1 4 (this row shouldnt exist)
8 500 2 1 4 (this is the correct row)
Also would have to join it with DEMAND
#didierc response:
ID ID MAX(S.PRIORITY) QUANTITY CASE_ID PHASE_ID
1 8 10 500 2 4
2 13 10 81 2 1
2 14 10 83 2 2
2 15 10 84 2 3
3 21 10 81 2 1
4 31 10 86 2 3
4 32 10 80 2 4
4 29 10 85 2 1
4 30 10 81 2 2
we need for each DEMAND four rows with the quantity Value. In Case Base we have four quantity and in Case 2 we only change the quantity for phase 4. We need always four rows for each demand.
Database DEMAND_STATE data:
ID PRIORITY QUANTITY CASE_ID DEMAND_ID PHASE_ID
1 0 86 1 1 1
2 0 85 1 1 2
3 0 81 1 1 3
4 0 84 1 1 4
8 10 500 2 1 4
We need to obtain for all Demand in 'DEMAND' only the Quantity for Each Phase with MAX priority
I translate the above, according to your sample result set, as:
SELECT
D.ID, S.ID, MAX(S.PRIORITY), S.QUANTITY, S.CASE_ID, S.PHASE_ID
FROM DEMAND D
LEFT JOIN DEMAND_STATE S
ON D.ID = S.DEMAND_ID
GROUP BY S.PHASE_ID, S.DEMAND_ID
Update:
To get the maximum priority for each pair(demand_id,phase_id)n we use the following query:
SELECT
DEMAND_ID, PHASE_ID, MAX(PRIORITY) AS PRIORITY
FROM DEMAND_STATE
GROUP BY DEMAND_ID, PHASE_ID
Next, to retrieve the set of phases for a given demand, just make an inner join on demand state:
SELECT S.* FROM DEMAND_STATE S
INNER JOIN (
SELECT
DEMAND_ID, PHASE_ID, MAX(PRIORITY) AS PRIORITY
FROM DEMAND_STATE
GROUP BY DEMAND_ID, PHASE_ID
) S2
USING (DEMAND_ID,PHASE_ID, PRIORITY)
WHERE DEMAND_ID = 1
If you want to limit the possible cases, include a where clause in the query S2:
SELECT S.* FROM DEMAND_STATE S
INNER JOIN (
SELECT
DEMAND_ID, PHASE_ID, MAX(PRIORITY) AS PRIORITY
FROM DEMAND_STATE
WHERE CASE_ID IN (1,2)
GROUP BY DEMAND_ID, PHASE_ID
) S2
USING (DEMAND_ID,PHASE_ID, PRIORITY)
WHERE DEMAND_ID = 1
However, your comments and update indicates that MAX(PRIORITY) does not seem very relevant after all. My understanding is that you have a base case, which may be overriden by another case in a given scenario (that scenario is the pair base case + some other case). Clarify that point in your question body if this is incorrect. If that is the case, you may change the above query by replacing PRIORITY by CASE_ID:
SELECT S.* FROM DEMAND_STATE S
INNER JOIN (
SELECT
DEMAND_ID, PHASE_ID, MAX(CASE_ID) AS CASE_ID
FROM DEMAND_STATE
WHERE CASE_ID IN (1,2)
GROUP BY DEMAND_ID, PHASE_ID
) S2
USING (DEMAND_ID,PHASE_ID, CASE_ID)
WHERE DEMAND_ID = 1
The only reason I see from having a priority is if you wish to combine more than 2 cases, and use priority to select which case will prevail depending on the phase.
You may of course prepend an inner join on DEMAND to include the related demand data.
Use of subqueries should be able to do as you wish, if I understand your question correctly. Something along the lines of the following:
SELECT
P.ID,
P.QUANTITY,
P.CASE_ID,
P.DEMAND_ID,
P.PHASE_ID
FROM DEMAND_STATE P
INNER JOIN (
-- Next level up groups it down and so gets the rows first returned for each PHASE_ID, which is the highest priority due to the subquery
SELECT
D.PHASE_ID,
D.PRIORITY,
D.DEMAND_ID
FROM (
-- Top level query to get all rows and order them in desc priority order
SELECT
S.PHASE_ID,
S.PRIORITY,
S.DEMAND_ID
FROM DEMAND_STATE S
WHERE S.DEMAND_ID IN (1) -- Update this to be whichever DEMAND_IDs you are interested in
AND S.CASE_ID IN (1,2)
ORDER BY
S.PHASE_ID ASC,
S.DEMAND_ID ASC,
S.PRIORITY DESC
) D
GROUP BY
D.PHASE_ID,
S.DEMAND_ID
) SUB
ON SUB.PHASE_ID = P.PHASE_ID
AND SUB.DEMAND_ID = P.DEMAND_ID
The top level subquery exists to get the rows you are interested in and order them in an order which allows predictable results when they are then grouped down by PHASE_ID and DEMAND_ID. This in turn allows a simple INNER JOIN to DEMAND_STATE hopefully (unless I have misunderstood your query)
This may still be expensive though depending on how much data is within that top level query.

MySQL select using row counts and grouping

I have 2 tables, orders and order_lineitems.
orders contains the order status info (sold date, invoice no, type of sale, etc)
order_lineitems contains the item(s) for each order in a one to many relationship.
Since we provide shipping info by line item, ship_date is in the order_lineitems table, null if not shipped, a date if it is shipped.
I am trying to pull the orders where all items have shipped by comparing the number of line item rows against the line item rows that have a ship date. While I have successfully pulled all that info, I am unable to make the last step, limiting the result set to include only the completely shipped orders (number of rows = number of rows where ship_date is not null).
I know I am missing something simple, but just don't see it..
select sum(custom.lineitems) as totalitems, sum(custom.shipped) as totalshipped,
custom.invoice, z.shipregion
from (
select a.invoice, count(a.invoice) as lineitems, 0 as shipped
from order_lineitem a
group by a.invoice
UNION ALL
select b.invoice, 0 as notshipped, count(b.ship_date) as shipped
from order_lineitem b
where b.ship_date is not null
group by b.invoice
) as custom
left join orders z on custom.invoice = z.invoice
where z.result = 0
and z.respmsg like 'Approved%'
and z.shipregion <> 'PENDING'
and z.cancelorder = 0
group by custom.invoice;
This returns a result set like so (one row for each invoice in the DB)
totalitems totalshipped invoice shipregion
4 2 1000 REGION08
1 1 10001 REGION07
1 1 10004 REGION05
3 1 10006 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
What I am looking for is a result set like this - only where totalitems = totalshipped
totalitems totalshipped invoice shipregion
1 1 10001 REGION07
1 1 10004 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
Use HAVING clause
SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice HAVING lineitems = shipped
OR
SELECT a.invoice, a.shipregion, a.lineitems, a.shipped
FROM (SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice
) AS a WHERE a.lineitems = a.shipped
One more outer query needed.
select * from
(
\\Your whole query here
) as Result
where Result.totalitems = Result.totalshipped

Select last Order state from Orders

I have tables:
orders:
id_order id_customer
1 1
2 2
3 1
orders_history
id_history id_order id_order_state date_add
1 1 1 2010-01-01 00:00:00
2 1 2 2010-01-02 00:00:00
3 1 3 2010-01-03 00:00:00
4 2 2 2010-05-01 00:00:00
5 2 3 2011-05-02 00:00:00
6 3 1 2011-05-03 00:00:00
7 3 2 2011-06-01 00:00:00
order_state
id_order_state name
1 New
2 Sent
3 Rejected
4 ...
How to get all order_id's where last id_order_state of that order (by last I mean this with MAX(id_history) or MAX(date_add)) is not equal 1 or 3?
select oh.id_history, oh.id_order, oh.id_order_state, oh.date_add
from (
select id_order, max(date_add) as MaxDate
from orders_history
where id_order_state not in (1, 3)
group by id_order
) ohm
inner join orders_history oh on ohm.id_order = oh.id_order
and ohm.MaxDate = oh.date_add
I think what he's after is what orders are complete... ie their final status, not those that are exclusive of the 1 and 3 specifically. The first pre-query should be the max ID regardless of the status code
select
orders.*
from
( select oh.id_order,
max( oh.id_history ) LastID_HistoryPerOrder
from
orders_history oh
group by
oh.id_order ) PreQuery
join orders_history oh2
on PreQuery.ID_Order = oh2.id_order
AND PreQuery.LastID_HistoryPerOrder = oh2.id_history
AND NOT OH2.id_order_state IN (1, 3) <<== THIS ELIMINATES 1's & 3's from result set
join Orders <<= NOW, anything left after above ^ is joined to orders
on PreQuery.ID_Order = Orders.ID_Order
Just to re-show YOUR data... I've marked the last SEQUENCE (ID_History) per ORDER... This is what the PREQUERY is going to return...
id_history id_order id_order_state date_add
1 1 1 2010-01-01 00:00:00
2 1 2 2010-01-02 00:00:00
**3 1 3 2010-01-03 00:00:00
4 2 2 2010-05-01 00:00:00
**5 2 3 2011-05-02 00:00:00
6 3 1 2011-05-03 00:00:00
**7 3 2 2011-06-01 00:00:00
The "PreQuery" will result with the following subset
ID_Order LastID_HistoryPerOrder (ID_History)
1 3 (state=3) THIS ONE WILL BE SKIPPED IN FINAL RESULT
2 5 (state=3) THIS ONE WILL BE SKIPPED IN FINAL RESULT
3 7 (state=2)
Now, the result of this is then re-joined back to order history on just these two elements... yet adds the criteria to EXCLUDE the 1,3 entries for "order state".
In this case,
1 would be rejected as its state = 3 (sequence #3),
2 would be rejected since its last history is state = 3 (sequence #5).
3 would be INCLUDED since its state = 2 (sequence #7)
Finally, all that joined to the orders will result with ONE ID, and nicely match up with the orders table on the Order_ID alone and get the desired results.
Another possible solution:
SELECT DISTINCT
id_order
FROM
Orders_History OH1
LEFT OUTER JOIN Orders_History OH2 ON
OH2.id_order = OH1.id_order AND
OH2.is_order_state IN (1, 3) AND
OH2.date_add >= OH1.date_add
WHERE
OH2.id_order IS NULL
I'm using "answer for my question" because I need to post results of your queries. So.
Unfortunately not all of your answers guys works. Let's prepare test environment:
CREATE TABLE `order_history` (
`id_order_history` int(11) NOT NULL AUTO_INCREMENT,
`id_order` int(11) NOT NULL,
`id_order_state` int(11) NOT NULL,
`date_add` datetime NOT NULL,
PRIMARY KEY (`id_order_history`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=latin2;
CREATE TABLE `orders` (
`id_order` int(11) NOT NULL AUTO_INCREMENT,
`id_customer` int(11) DEFAULT NULL,
PRIMARY KEY (`id_order`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin2;
INSERT INTO `order_history`
(`id_order_history`, `id_order`, `id_order_state`, `date_add`) VALUES
(1,1,1,'2011-01-01 00:00:00'),
(2,1,2,'2011-01-01 00:10:00'),
(3,1,3,'2011-01-01 00:20:00'),
(4,2,1,'2011-02-01 00:00:00'),
(5,2,2,'2011-02-01 00:25:01'),
(6,2,3,'2011-02-01 00:25:59'),
(7,3,1,'2011-03-01 00:00:01'),
(8,3,2,'2011-03-01 00:00:02'),
(9,3,3,'2011-03-01 00:01:00'),
(10,3,2,'2011-03-02 00:00:01');
COMMIT;
INSERT INTO `orders` (`id_order`, `id_customer`) VALUES
(1,1),
(2,2),
(3,3),
(4,4),
(5,5),
(6,6),
(7,7);
COMMIT;
Now, lets select Last/Max State for each Order, so let's run simple query:
select id_order, max(date_add) as MaxDate
from `order_history`
group by id_order
this gives us PROPER results, no rocket science right now:
id_order MaxDate
---------+-------------------
1 2011-01-01 00:20:00 //last order_state=3
2 2011-02-01 00:25:59 //last order_state=3
3 2011-03-02 00:00:01 //last order_state=2
Now for simplicity, lest change our queries to get Orders where Last State is not equal 3.
We're expecting to get one row result with id_order = 3.
So let's test our queries:
QUERY 1 made by RedFilter:
select oh.id_order, oh.id_order_state, oh.date_add
from (
select id_order, max(date_add) as MaxDate
from `order_history`
where id_order_state not in (3)
group by id_order
) ohm
inner join `order_history` oh on ohm.id_order = oh.id_order
and ohm.MaxDate = oh.date_add
Result:
id_order id_order_state date_add
-------------------------------------------------
1 2 2011-01-01 00:10:00
2 2 2011-02-01 00:25:01
3 2 2011-03-02 00:00:01
So it's not true
QUERY 2 made by Tom H.:
SELECT DISTINCT OH1.id_order
FROM order_history OH1
LEFT OUTER JOIN order_history OH2 ON
OH2.id_order = OH1.id_order AND
OH2.id_order_state NOT IN (3) AND
OH2.`id_order_history` >= OH1.`id_order_history`
WHERE
OH2.id_order IS NULL
Result:
id_order
--------
1
2
So it's not true
Any suggestions appreciated.
EDIT
Thanks to Andriy M. comment we have proper solution. It's a modification of Tom H. query all should looks as follow:
SELECT DISTINCT
OH1.id_order
FROM
order_history OH1
LEFT OUTER JOIN order_history OH2 ON
OH2.id_order = OH1.id_order
AND OH2.date_add > OH1.date_add
WHERE OH1.id_order_state NOT IN (3) AND OH2.id_order IS NULL
EDIT 2:
QUERY 3 made by DRapp:
select
distinct orders.`id_order`
from
( select oh.id_order,
max( oh.id_order_history ) LastID_HistoryPerOrder
from
order_history oh
group by
oh.id_order ) PreQuery
join order_history oh2
on PreQuery.id_order = oh2.id_order
AND PreQuery.LastID_HistoryPerOrder = oh2.id_order_history
AND NOT oh2.id_order_state IN (1,3)
join orders
on PreQuery.id_order = orders.id_order
Result:
id_order
--------
3
So it's finally true