mysql select column outside group by - mysql

I have the following dataset
ID P C1 C2 XR
1 1 GBP USD 1.6
2 2 GBP USD 1.7
3 1 GBP EUR 0.84
4 2 GBP EUR 0.83
5 1 GBP CHF 1.8
6 2 GBP CHF 1.8
I'm trying to get the minimum XR for each pair so the results should be
ID P C1 C2 XR
1 1 GBP USD 1.6
4 2 GBP EUR 0.83
5 1 GBP CHF 1.8
but when I SELECT MIN(XR) GROUP BY C1,C2, I either dont get the correct ID or get a warning saying ID not in GROUP BY if 'ONLY_FULL_GROUP_BY' enabled
Closest I've got is this:
SELECT t1.id, t1.C1, t1.C2, MIN(t2.XR) FROM xrates t1
LEFT JOIN xrates AS t2 ON t1.id = t2.id
GROUP BY t1.id, t1.C1, t1.C2
HAVING t1.C1 = 'GBP' AND t1.C2 IN ('USD','EUR')

select rates.*
from xrates rates
where id in
(
select min(xrates.id) as minid
from xrates
inner join
(
select C1, C2, MIN(XR) as minxr
from xrates
GROUP BY C1, C2
HAVING C1 = 'GBP'
) x on x.c1 = xrates.c1 and x.c2 = xrates.c2 and x.minxr = xrates.xr
group by xrates.C1, xrates.C2
)
SQLFiddle demo

SELECT x.*
FROM my_table x
JOIN
(SELECT grouping _id,MIN(ordering_id) min_ordering_id FROM my_table GROUP BY grouping_id) y
ON y.grouping_id = x.grouping_id
AND y.min_ordering_id = x.ordering_id;
(note that the 'grouping_id' may be formed on more than one column!)

You don't need to join the table to itself, and you do not want to GROUP BY the id or every row is going to be unique. The following should return the results you specify:
SELECT
xrates.id,
xrates.C1,
xrates.C2,
MIN(xrates.XR)
FROM xrates
WHERE xrates.C1 = 'GBP'
AND xrates.C2 IN ('USD','EUR')
GROUP BY
xrates.C1,
xrates.C2;

Related

Replace null value by latest value

Say I have below table. How do I pick up the latest previous value in case my joined table to not match the date and currency? On the null DKK value I want it to pick up 3. Note that dates do not exist every day since I do not load the tables on weekends.
Select
PositionDate,
Currency,
T2.Value,
isnull(t2.value, ? )
From t1
left join t2
on t1.currency = t2.Currency
and t1.PositionDate = t2.PositionDate
.
PositionDate Currency Value
2017-04-11 SEK 1
2017-04-11 DKK NULL
2017-04-11 EUR 7
2017-04-10 SEK 4
2017-04-10 DKK 3
2017-04-10 EUR 5
2017-04-07 SEK 4
2017-04-07 DKK 3
2017-04-07 EUR 5
.
This will work for your case i think:
SELECT
t1.PositionDate,
t1.Currency,
COALESCE(t1.Value,t2.value) AS Value
FROM t1
LEFT join (SELECT MAX(PositionDate) AS PositionDate,Currency FROM t2 WHERE PositionDate < t1.PositionDate GROUP BY Currency) tjoin
LEFT join t2 on tjoin.currency = t2.Currency and tjoin.PositionDate = t2.PositionDate
You can Achieve it by using CTE and Case condition.
With cte as
(
Select
PositionDate,
Currency,
T2.Value,
From t1
left join t2
on t1.currency = t2.Currency
and t1.PositionDate = t2.PositionDate
and t1.PositionDate = t2.PositionDate
)
select PositionDate, Currency, Value,
CASE WHEN ISNULL(value,'')='' THEN
(Select top 1 from cte cin where cin.currency=cout.currency order by CONVERT(Date,PositionDate) desc)
ELSE
Value
END as Value2
From cte cout

Mysql left join fails to returns all values from first table

I've two tables named table1 and table2. table2 may have elements from table1. I'd like to show all the results from table2 with the price if available in table1 and with status 1. If no product matches in table1 and also status is 0, need to return price as 0.
table1
id pname item_code price status
1 product1 abcd 200 1
2 product2 pqrs 500 1
3 product3 wxyz 425 1
4 product5 mnop 100 0
and table2 as follows
id item_code
10 efgh
11 abcd
12 pqrs
13 mnop
I have tried following query
SELECT `t2`.`id`, `t2`.`item_code`, `t1`.`price`,`t1`.`pname`, COUNT(t2.item_code) AS sellers FROM (`table2` as t2) LEFT JOIN `table1` as t1 ON `t1`.`item_code` = `t2`.`item_code` WHERE `t1`.`status` = 1 GROUP BY `t2`.`item_code`
but it returns common values in table1 and table2 with status 1, but I need all records from table2 with price as 0 if nothing match in table1 or status 0 in table1.
Expected output
id item_code price
10 efgh 0
11 abcd 200
12 pqrs 500
13 mnop 0
Any help please.
Thanks,
Not sure about your current query which is having count and group by however you can do as below
select
t2.id,
t2.item_code,
case
when t1.status = 1 then t1.price
else 0
end as price
from table2 t2
left join table1 t1 on t1.item_code = t2.item_code
Now note that if table1 has multiple matching values from table2 in that case we may need grouping data.
Try below query:
SELECT `t2`.`id`, `t2`.`item_code`, `t1`.`price`,`t1`.`pname`, COUNT(t2.item_code) AS sellers FROM (`table2` as t2) LEFT JOIN (select * from table1 where status = 1)t1 ON `t1`.`item_code` = `t2`.`item_code` GROUP BY `t2`.`item_code`
Move the part of the WHERE clause that checks the left joined table to the ON clause
SELECT `t2`.`id`, `t2`.`item_code`, COALESCE(`t1`.`price`, 0),`t1`.`pname`, COUNT(t2.item_code) AS sellers
FROM (`table2` as t2)
LEFT JOIN `table1` as t1
ON `t1`.`item_code` = `t2`.`item_code`
AND`t1`.`status` = 1
GROUP BY `t2`.`item_code`

MySql JOIN two tables SUM wrong result from left table

I have a two table and I have left join and want sum of value from both table.
But the result from second table not retrieved successfully (SUM not group by properly)
Table test1
id redeem_count cost camp_id
1 2 500 1
2 3 1000 1
3 2 2000 2
4 2 3000 2
5 2 1200 3
Table test2
id bill_amount earning test1_id
1 4000 50 1
2 5000 55 3
3 6000 60 4
Output
camp_id redeem cost bill earning
1 5 1500 15000 165
2 4 5000 NULL NULL
3 2 1200 NULL NULL
Desired Result
camp_id redeem cost bill earning
1 5 1500 4000 50
2 4 5000 11000 115
3 2 1200 0 0
I have execute following SQL.
SELECT
t1.camp_id,
t1.redeem,
t1.cost,
t2.bill,
t2.earning
FROM (SELECT COALESCE(SUM(redeem_count),0) AS redeem, COALESCE(SUM(cost),0) AS cost, id,camp_id FROM test1 GROUP BY camp_id) t1
LEFT JOIN(SELECT COALESCE(SUM(bill_amount),0) AS bill, COALESCE(SUM(earning),0) AS earning, test1_id FROM test2) t2
ON t1.id = t2.test1_id
How can I achieve desired result? Would you please provide the solution?
SELECT
t1.camp_id,
t1.redeem,
t1.cost,
t2.bill,
t2.earning
FROM (SELECT COALESCE(SUM(redeem_count),0) AS redeem, COALESCE(SUM(cost),0) AS cost, id,camp_id FROM test1 GROUP BY camp_id) t1
LEFT JOIN(SELECT COALESCE(bill_amount) AS bill, COALESCE(earning) AS earning, test1_id FROM test2) t2
ON t1.id = t2.test1_id
try this:
SELECT
t1.camp_id,
t1.redeem,
t1.cost,
t2.bill,
t2.earning
FROM (SELECT COALESCE(SUM(redeem_count),0) AS redeem, COALESCE(SUM(cost),0) AS cost, id,camp_id FROM test1 GROUP BY camp_id) t1
LEFT JOIN(SELECT COALESCE(bill_amount) AS bill, COALESCE(earning) AS earning, test1_id FROM test2) t2
ON t1.id = t2.test1_id
update:1
SELECT
t1.camp_id,
t1.redeem,
t1.cost,
t2.bill,
t2.earning
FROM
(
SELECT
COALESCE(SUM(redeem_count),0) AS redeem,
COALESCE(SUM(cost),0) AS cost,
id,
camp_id
FROM test1
GROUP BY camp_id) t1
LEFT JOIN(
SELECT
SUM(bill_amount) AS bill,
SUM(earning) AS earning, test1_id FROM test2 GROUP BY test1_id) t2
ON t1.camp_id= t2.test1_id
My code produced output like:
camp_id redeem cost bill earning
1 5 1500 4000 50
2 4 5000 11000 115
3 2 1200 (NULL) (NULL)
EDITED
Create your subquery like when you want to query only the required result, then join those results.
(Query is not tested!)
SELECT
X1.camp_id
, X1.redeem
, X1.redeem
, X2.cost
, X2.earning
FROM
(
SELECT
SUM(redeem_count) AS redeem,
SUM(cost) AS cost,
id,
camp_id
FROM
test1
GROUP BY
camp_id
) X1
LEFT JOIN (
SELECT
T1.camp_id,
SUM(T2.bill_amount) AS bill,
SUM(T2.earning) AS earning
FROM
test1 T1
INNER JOIN test2 T2
ON T1.id = T2.id
GROUP BY
T1.camp_id
) X2
ON X1.camp_id = X2.camp_id

How do I select the min and max values using a self join

I have a table that looks like this:
pk client value date
1 001 564 2012/5/1
2 002 245 2012/6/1
3 003 445 2012/6/6
4 001 845 2012/7/1
5 002 567 2012/8/1
6 001 123 2012/9/1
I know this can be solved with the greatest n per group and a self join, but I'm having trouble figuring it out.
Basically this is what I want for my output
client min(value) max(value) date_for_min(value) date_for_max(value)
001 123 845 2012/9/1 2012/7/1
002 245 567 2012/6/1 2012/8/1
003 445 445 2012/6/6 2012/6/6
The tricky part is getting only one row for each client with the min / max values and then the other columns that go along with those min / max values. Any ideas?
In the case there are multiple rows for some min or max value (for same client), I have given you the earliest date that they appear:
select t1.client, t1.MinValue, t1.MaxValue, min(t2.date) as date_for_min_value, min(t3.date) as date_for_max_value
from (
select client, min(value) as MinValue, max(value) as MaxValue
from MyTable
group by client
) t1
inner join MyTable t2 on t1.client = t2.client and t1.MinValue = t2.Value
inner join MyTable t3 on t1.client = t3.client and t1.MaxValue = t3.Value
group by t1.client, t1.MinValue, t1.MaxValue
You can use the following:
select distinct t1.client, t1.mnval, mindate.dt, t1.mxval, maxdate.dt
from
(
select min(value) mnval, max(value) mxVal, client
from yourtable
group by client
) t1
inner join yourtable t2
on t1.client = t2.client
inner join yourtable mindate
on t1.client = mindate.client
and t1.mnval = mindate.value
inner join yourtable maxdate
on t1.client = maxdate.client
and t1.mxVal = maxdate.value

select from one table where count=1 in second table and two more conditions

I need to select transactions with cash payment and same date but only for those transactions
which have only one payment ( so num 14 should be omitted from resultset )
So correct result is 12 and 13 only.
Table2 Table1
num | date | data | total num | payment | date
12 xy abc 2.5 12 cash xy
13 xy cbc 2.1 13 cash xy
14 xy acc 2.3 14 visa xy
19 xy def 2.0 14 cash xy
27 xy fgh 1.3 19 visa xy
27 mc xy
Something like this gives num 14 in result-set but 14 should be omitted.
SELECT num, data
FROM Table2
WHERE num IN
(
SELECT num FROM `Table1`
WHERE payment = 'cash'
GROUP BY `num`
HAVING ( COUNT(`num`) = 1 )
)
To sumarize correct answer (by tombom ):
SELECT t2.num, t2.data
FROM Table1 as t1
INNER JOIN Table2 as t2 ON t1.num = t2.num
AND t1.date = 'xy'
GROUP BY t1.num
HAVING GROUP_CONCAT(t1.payment) = 'cash'
Thanks!
I'm sorry, I totally misunderstood your question. Here's how it works:
SELECT
*
FROM
Table1 t1
INNER JOIN Table2 t2 ON t1.num = t2.num AND t1.date = t2.date
GROUP BY t1.num
HAVING GROUP_CONCAT(t1.payment) = 'cash'