My database structure contains columns: id, name, value, dealer. I want to retrieve row with lowest value for each dealer. I've been trying to mess up with MIN() and GROUP BY, still - no solution.
Solution1:
SELECT t1.* FROM your_table t1
JOIN (
SELECT MIN(value) AS min_value, dealer
FROM your_table
GROUP BY dealer
) AS t2 ON t1.dealer = t2.dealer AND t1.value = t2.min_value
Solution2 (recommended, much faster than solution1):
SELECT t1.* FROM your_table t1
LEFT JOIN your_table t2
ON t1.dealer = t2.dealer AND t1.value > t2.value
WHERE t2.value IS NULL
This problem is very famous, so there is a special page for this in Mysql's manual.
Check this: Rows Holding the Group-wise Maximum/Minimum of a Certain Column
select id,name,MIN(value) as pkvalue,dealer from TABLENAME
group by id,name,dealer;
here you group all rows by id,name,dealer and then you will get min value as pkvalue.
SELECT MIN(value),dealer FROM table_name GROUP BY dealer;
First you need to resolve the lowest value for each dealer, and then retrieve rows having that value for a particular dealer. I would do this that way:
SELECT a.*
FROM your_table AS a
JOIN (SELECT dealer,
Min(value) AS m
FROM your_table
GROUP BY dealer) AS b
ON ( a.dealer= b.dealer
AND a.value = b.m )
Try following:
SELECT dealer, MIN(value) as "Lowest value"
FROM value
GROUP BY dealer;
select id, name, value, dealer from yourtable where dealer
in(select min(dealer) from yourtable group by name, value)
These answers seem to miss the edge case of having multiple minimum values for a dealer and only wanting to return one row.
If you want to only want one value for each dealer you can use row_number partition - group - the table by dealer then order the data by value and id. we have to make the assumption that you will want the row with the smallest id.
SELECT ord_tbl.id,
ord_tbl.name,
ord_tbl.value,
ord_tbl.dealer
FROM (SELECT your_table.*,
ROW_NUMBER() over (PARTITION BY dealer ORDER BY value ASC, ID ASC)
FROM your_table
) AS ord_tbl
WHERE ord_tbl.ROW_NUMBER = 1;
Be careful though that value, id and dealer are indexed. If not this will do a full table scan and can get pretty slow...
Related
Objective:
I wanted to show the number of distinct IDs for any combination selected.
In the below example, I have data at a granular level: ID level data.
I wanted to show the number of distinct IDs for each combination.
For this, I use count distinct which will give me '1' for the below combinations.
But let's say if I wanted to find the number of IDs who made both E-commerce and Face to face transactions, in that case, if I just use this data, I would be showing the sum of E-comm and Face to face and the result would be '2' instead of '1'.
And this is not limited to Ecom/Face to face. I wanted to apply the same logic for all columns.
Please let me know if you have any other alternative approach to address this issue.
First aggregate in your table to get the distinct ids for each TranType:
SELECT TranType, COUNT(DISTINCT id) counter_distinct
FROM tablename
GROUP BY TranType
and then join to the table:
SELECT t.*, g.counter_distinct
FROM tablename t
INNER JOIN (
SELECT TranType, COUNT(DISTINCT id) counter_distinct
FROM tablename
GROUP BY TranType
) g ON g.TranType = t.TranType
Or use a correlated subquery:
SELECT t1.*,
(SELECT COUNT(DISTINCT t2.id) FROM tablename t2 WHERE t2.TranType = t1.TranType) counter_distinct
FROM tablename t1
But let's say if I wanted to find the number of IDs who made both E-commerce and Face to face transactions, in
You can get the list of ids using:
select id
from t
where tran_type in ('Ecomm', 'Face to face')
group by id
having count(distinct tran_type) = 2;
You can get the count using a subquery:
select count(*)
from (select id
from t
where tran_type in ('Ecomm', 'Face to face')
group by id
having count(distinct tran_type) = 2
) i;
Table: MyTable
[
Here is the result I desire:
For every ID in the table, count how many times that ID appears in the column Parent_ID.
Create a custom column AS Instances to place the result.
My desired Result
I imagine to get the above result with something not more complicated than a working version of the following query:
SELECT ID, Parent_ID, COUNT( Parent_ID = ID ) AS Instances FROM MyTable
You can use a scalar subquery to compute the extra column. For example:
select
id,
parent_id,
(
select count(*) from my_table b where b.parent_id = a.id
) as instances
from my_table a
A correlated subquery is the simplest solution:
select t.*,
(select count(*) from mytable t2 where t2.parent_id = t.id) as instances
from mytable t;
I want to know how can I find duplicate value in a table over two columns combined.
suppose my table has fields as id || name || father_name || region || dob
now how can I find results set such as:
.ie I want to find all rows where three columns are same.
select t1.*
from your_table t1
join
(
select name, father_name, region
from your_table
group by name, father_name, region
having count(*) >= 3
) t2 on t1.name = t2.name
and t1.father_name = t2.father_name
and t1.region = t2.region
If you are using MySql 8.0, you could make use of window function. Below query with such function returns exact output:
select id, name, fatherName, country from (
select id,
name,
fatherName,
country,
count(id) over (partition by name, fatherName, country) cnt
from Tbl
) `a` where cnt > 1;
Actually, i also need this type of feature many times, where i need to compare all columns with same value except auto incremented primary key id column.
So, in that case i always use group by keyword.
Example,
SELECT A.*
FROM YourTable A
INNER JOIN (SELECT name,city,state
FROM YourTable
GROUP BY name,city,state
HAVING COUNT(*) > 1) B
ON A.name = B.name AND A.city = B.city AND A.state = B.state
You can append the number of columns which you want to compare
Hope, This might help you in your case also.
I have a table opname like this:
I want to select table opname with group by based id_barang and I want to display the row with the highest id of group by result.
I wrote query like this
SELECT
MAX(id), id_barang, tgl, ket, kondisi
FROM
`opname`
GROUP BY
id_barang
but why value of columns tgl, ket, kondisi it's not match with max(id) - how to fix that? I want to display row with the highest id of group by result
You can use the following using a sub-query:
SELECT id, id_barang, tgl, ket, kondisi FROM `opname` WHERE id IN (
SELECT MAX(id) FROM `opname` GROUP BY id_barang
)
With the inner SELECT you get all the maximum IDs of the grouped result. The outer SELECT selects all rows from your original table with all these IDs.
Your current query is not far off, except that it attempts to select non aggregate columns while using GROUP BY. This doesn't make logical sense, because it isn't clear which values should be chosen for each id_barang group. But if we join the opname table to your current query as a subquery, then we can identify the records you want to retain.
SELECT t1.*
FROM opname t1
INNER JOIN
(
SELECT id_barang, MAX(id) AS max_id
FROM opname
GROUP BY id_barang
) t2
ON t1.id_barang = t2.id_barang AND -- retain only MAX(id) records
t1.id = t2.max_id -- for each barang_id
I have table with id, item_id, value (int), run (datetime) and i need select value diff betwen last two run per *item_id*.
SELECT item_id, ABS(value1 - value2) AS diff
FROM ( SELECT h.item_id, h.value AS value1, h2.value AS value2
FROM ( SELECT id, item_id, value
FROM table_name
GROUP BY item_id
ORDER BY run DESC) AS h
INNER JOIN ( SELECT id, item_id, value
FROM table_name
ORDER BY run DESC) AS h2
ON h.item_id = h2.item_id AND h.id != h2.id
GROUP BY item_id) AS h3
I believe this should do the trick for you. Just replace table_name to correct name.
Explanation:
Basicly I join the table with itself in a run DESC order, JOIN them based on item_id but also on id. Then I GROUP BY them again to remove potential 3rd and so on cases. Lastly I calculate the difference between them through ABS(value1 - value2).
SELECT t2.id, t2.item_id, (t2.value- t1.value) valueDiff, t2.run
FROM ( table_name AS t1
INNER JOIN
table_name AS t2
ON t1.run = (SELECT MAX(run) FROM table_name where run < t2.run)
and t1.item_id = t2.item_id)
This is assuming you want the diff between a record and the record with the previous run