SQL One to Many column association rows - mysql

Given the table below I want to select the rows for which the same 'CODE' is associated with multiple 'SUB_CODE'.
+------+------------+-------------+
| DIV | CODE | SUB_CODE |
+------+------------+-------------+
| 11 | 1000 | 1212 |
| 11 | 1000 | 1213 |
| 11 | 1000 | 3434 |
| 11 | 1000 | 1000 |
| 11 | 1000 | 3000 |
| 11 | 3000 | 1213 |
| 11 | 2000 | 1212 |
| 20 | 1500 | 5656 |
| 20 | 1500 | 1213 |
+------+------------+-------------+
For the above table the result should be
+------+------------+-------------+
| DIV | CODE | SUB_CODE |
+------+------------+-------------+
| 11 | 1000 | 1212 |
| 11 | 1000 | 1213 |
| 11 | 1000 | 3434 |
| 11 | 1000 | 1000 |
| 11 | 1000 | 3000 |
| 11 | 1500 | 5656 |
| 11 | 1500 | 1213 |
+------+------------+-------------+
This is what I tried, how ever my results fails.
Select CODE from TABLE_NAME where (count(SUB_CODE) > 1);

First fetch the CODEs for which multiple SUB_CODEs exists; then project the table columns filtering using the above results as a nested query:
select * from TABLE_NAME where CODE in
(select CODE from TABLE_NAME group by CODE having count(SUB_CODE) > 1);
demo: http://sqlfiddle.com/#!9/1d91f/3/0

TRY THIS:
Select `DIV`, `CODE`, `SUB_CODE` from TABLE_NAME GROUP BY `SUB_CODE`

Related

Sort Columns by Column_Totals through Alter Table or Select Query in MySQL at Runtime

I want to alter or generate Select Query of the Source_Table below at runtime by getting the column total (sum) first then sort according to its result:
Source_Table:
+----+------------+-----------+-----------+-----------+-----------+-----------+
| ID | Name | Field_1 | Field_2 | Field_3 | Field_4 | Field_5 |
+----+------------+-----------+-----------+-----------+-----------+-----------+
| 1 | abc | 10 | 18 | 5 | 21 | 6 |
+----+------------+-----------+-----------+-----------+-----------+-----------+
| 2 | ghq | 22 | 14 | 12 | 11 | 23 |
+----+------------+-----------+-----------+-----------+-----------+-----------+
| 3 | xyz | 35 | 8 | 16 | 7 | 4 |
+----+------------+-----------+-----------+-----------+-----------+-----------+
The Result_Table I am looking at is:
|--------------- sorted fields based on total --------------|
+------------+-----------+-----------+-----------+-----------+-----------+
| Name | Field_5 | Field_3 | Field_4 | Field_2 | Field_1 |
+------------+-----------+-----------+-----------+-----------+-----------+
| abc | 4 | 5 | 21 | 18 | 10 |
+------------+-----------+-----------+-----------+-----------+-----------+
| ghq | 23 | 12 | 11 | 14 | 22 |
+------------+-----------+-----------+-----------+-----------+-----------+
| xyz | 4 | 16 | 7 | 8 | 35 |
+------------+-----------+-----------+-----------+-----------+-----------+
| Total | 31 | 33 | 39 | 40 | 67 | --> get column sum and sort from lowest to highest
+------------+-----------+-----------+-----------+-----------+-----------+
I am not so sure if this is possible with MySQL as I am not able to find good reference in the internet for this case. But I will try..

Unexpected SUM result found using SUM with JOIN query [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have two tables 'tbl_orders' and 'tbl_instore'. tbl_orders have 'sel_product_qty' which I want to date wise SUM and table(tbl_instore) have 'inst_prod_qty' and 'chln_amount' which I calculate and want to get purchased unit price. But when I use join query on those two tables, the SUM(sel_product_qty) produces double, triple and quadruple amount from the expected result.
Sample data tables are..
Table "tbl_order":
+----------+------------+------------+-----------------+---------------+--------------------+
| order_id | ord_det_id | product_id | sel_product_qty | selling_price | order_date_time |
+----------+------------+------------+-----------------+---------------+--------------------+
| 3 | 1 | 4 | 50 | 67.82 | 2019-03-21 21:52:21|
| 4 | 1 | 1 | 100 | 37.88 | 2019-03-21 21:52:21|
| 5 | 2 | 4 | 120 | 67.82 | 2018-03-23 00:02:36|
| 6 | 3 | 3 | 300 | 123.67 | 2019-03-23 00:04:38|
| 7 | 3 | 2 | 50 | 76.28 | 2019-03-23 00:04:38|
| 8 | 4 | 4 | 50 | 67.82 | 2019-03-24 12:13:06|
| 9 | 4 | 2 | 100 | 76.28 | 2019-03-24 12:13:06|
| 10 | 5 | 1 | 10 | 37.88 | 2019-03-25 12:56:40|
| 11 | 5 | 4 | 7 | 67.82 | 2019-03-25 12:56:40|
| 12 | 6 | 4 | 23 | 67.82 | 2019-03-29 00:29:14|
| 13 | 6 | 2 | 25 | 76.28 | 2019-03-29 00:29:14|
| 16 | 7 | 1 | 120 | 37.88 | 2019-04-14 16:51:10|
| 17 | 7 | 3 | 90 | 123.67 | 2019-04-14 16:51:11|
| 18 | 8 | 1 | 100 | 66.95 | 2019-04-22 23:30:39|
| 19 | 8 | 2 | 22 | 70.04 | 2019-04-22 23:30:39|
+----------+------------+------------+-----------------+---------------+--------------------+
Table "tbl_instore":
+----------+----------+------------+---------------+-------------+--------------------+
| in_st_id | s_inv_id | product_id | inst_prod_qty | chln_amount | instore_date_time |
+----------+----------+------------+---------------+-------------+--------------------+
| 1 | 1 | 1 | 1000 | 65852 | 2/14/2018 17:28 |
| 14 | 9 | 1 | 100 | 6400 | 4/26/2019 8:26 |
| 3 | 2 | 1 | 2000 | 58885 | 3/19/2019 17:32 |
| 5 | 3 | 1 | 100 | 3588 | 3/19/2019 17:35 |
| 11 | 7 | 1 | 1000 | 65000 | 4/22/2019 23:17 |
| 9 | 5 | 1 | 100 | 6345 | 4/20/2019 0:13 |
| 12 | 8 | 2 | 100 | 7800 | 4/22/2019 23:20 |
| 8 | 4 | 2 | 2000 | 144567 | 3/23/2019 0:04 |
| 7 | 4 | 3 | 1000 | 121665 | 3/23/2019 0:04 |
| 13 | 8 | 3 | 150 | 32000 | 4/22/2019 23:20 |
| 15 | 9 | 3 | 100 | 19000 | 4/26/2019 8:26 |
| 10 | 6 | 4 | 1000 | 88022 | 4/20/2019 0:16 |
| 6 | 3 | 4 | 100 | 6582 | 3/19/2019 17:35 |
| 4 | 2 | 4 | 1000 | 65882 | 3/19/2019 17:32 |
| 2 | 1 | 4 | 5000 | 359877 | 2/14/2018 17:28 |
+----------+----------+------------+---------------+-------------+--------------------+
The following query I have currently tried:
SELECT SUM(tbl_orders.sel_product_qty) AS `sel_prod_qty`,
(SUM(chln_amount) / SUM(inst_prod_qty)) AS `pur_uni_price`,
date_format(`order_date_time`, '%M-%Y') as `month`,
tbl_orders.product_id AS `product_id`
FROM tbl_orders
INNER JOIN tbl_instore ON tbl_instore.product_id = tbl_orders.product_id
WHERE YEAR(`order_date_time`)= '2019'
GROUP BY `month`, `product_id`;
Which return the following result:
+--------------+---------------+--------+------------+
| sel_prod_qty | pur_uni_price | month | product_id |
+--------------+---------------+--------+------------+
| 1320 | 47.923256 | Apr-19 | 1 |
+--------------+---------------+--------+------------+
| 44 | 72.555714 | Apr-19 | 2 |
+--------------+---------------+--------+------------+
| 270 | 138.132 | Apr-19 | 3 |
+--------------+---------------+--------+------------+
| 660 | 47.923256 | Mar-19 | 1 |
+--------------+---------------+--------+------------+
| 350 | 72.555714 | Mar-19 | 2 |
+--------------+---------------+--------+------------+
| 900 | 138.132 | Mar-19 | 3 |
+--------------+---------------+--------+------------+
| 520 | 73.290563 | Mar-19 | 4 |
+--------------+---------------+--------+------------+
If I run the query individually without JOIN, I will get SUM(sel_prod_qty) value as following (also my expected result should be):
+--------------+---------------+--------+------------+
| sel_prod_qty | pur_uni_price | month | product_id |
+--------------+---------------+--------+------------+
| 220 | 47.923256 | Apr-19 | 1 |
+--------------+---------------+--------+------------+
| 22 | 72.555714 | Apr-19 | 2 |
+--------------+---------------+--------+------------+
| 90 | 138.132 | Apr-19 | 3 |
+--------------+---------------+--------+------------+
| 110 | 47.923256 | Mar-19 | 1 |
+--------------+---------------+--------+------------+
| 175 | 72.555714 | Mar-19 | 2 |
+--------------+---------------+--------+------------+
| 300 | 138.132 | Mar-19 | 3 |
+--------------+---------------+--------+------------+
| 130 | 73.290563 | Mar-19 | 4 |
+--------------+---------------+--------+------------+
So, my question is, why does my query return SUM(sel_product_qty) double, triple and quadruple amount from the expected result?
Try this:
SELECT `sel_prod_qty`,
`pur_uni_price`,
`month`,
orders.product_id AS `product_id`
FROM
(SELECT product_id,SUM(sel_product_qty) AS `sel_prod_qty`,
DATE_FORMAT(`order_date_time`, '%M-%Y') AS `month`
FROM tbl_orders
WHERE YEAR(`order_date_time`)='2019'
GROUP BY `month`, `product_id`) orders
INNER JOIN
(SELECT product_id,(SUM(chln_amount) / SUM(inst_prod_qty)) AS `pur_uni_price`
FROM tbl_instore GROUP BY product_id) instore
ON orders.product_id=instore.product_id;
I created two sub-query from those tables that you joined because what doesn't work is that you are doing INNER JOIN ... ON tbl_instore.product_id = tbl_orders.product_id. Which if you refer back to your table, those value were repeated multiple times in both tables. Therefore, this sub-queries will perform the mathematical operation and the outer query will only return the results from it.
The pur_uni_price field is not an aggregate field anymore, therefore you need to add it on your GROUP BY. See code below
SELECT SUM(tbl_orders.sel_product_qty) AS `sel_prod_qty`,
(SUM(chln_amount) / SUM(inst_prod_qty)) AS `pur_uni_price`,
date_format(`order_date_time`, '%M-%Y') as `month`,
tbl_orders.product_id AS `product_id`
FROM tbl_orders
INNER JOIN tbl_instore ON tbl_instore.product_id = tbl_orders.product_id
WHERE YEAR(`order_date_time`)= '2019'
GROUP BY `month`, `product_id`, (SUM(chln_amount) / SUM(inst_prod_qty))

MySQL Query for averages

good morning. I have this table:
mysql> select * from Data;
+---------------------------+--------+-------+
| affyId | exptId | level |
+---------------------------+--------+-------+
| 31315_at | 3 | 250 |
| 31324_at | 3 | 91 |
| 31325_at | 1 | 191 |
| 31325_at | 2 | 101 |
| 31325_at | 4 | 51 |
| 31325_at | 5 | 71 |
| 31325_at | 6 | 31 |
| 31356_at | 3 | 91 |
| 31362_at | 3 | 260 |
| 31510_s_at | 3 | 257 |
| 5321_at | 4 | 90 |
| 5322_at | 4 | 90 |
| 5323_at | 4 | 90 |
| 5324_at | 3 | 57 |
| 5324_at | 4 | 90 |
| 5325_at | 4 | 90 |
| AFFX-BioB-3_at | 3 | 97 |
| AFFX-BioB-5_at | 3 | 20 |
| AFFX-BioB-M_at | 3 | 20 |
| AFFX-BioB-M_at | 5 | 214 |
| AFFX-BioB-M_at | 7 | 20 |
| AFFX-BioB-M_at | 8 | 40 |
| AFFX-BioB-M_at | 9 | 20 |
| AFFX-HSAC07/X00351_M_at | 3 | 86 |
| AFFX-HUMBAPDH/M33197_3_st | 3 | 277 |
| AFFX-HUMTFFR/M11507_at | 3 | 90 |
| AFFX-M27830_3_at | 3 | 271 |
| AFFX-MurIL10_at | 3 | 8 |
| AFFX-MurIL10_at | 5 | 8 |
| AFFX-MurIL10_at | 6 | 4 |
| AFFX-MurIL2_at | 3 | 20 |
| AFFX-MurIL4_at | 5 | 78 |
| AFFX-MurIL4_at | 6 | 20 |
| U95-32123_at | 1 | 128 |
| U95-32123_at | 2 | 128 |
| U98-40474_at | 1 | 57 |
| U98-40474_at | 2 | 57 |
+---------------------------+--------+-------+
37 rows in set (0.00 sec)
If I wanna look for the average expression level (level) of each array probe (affyId) across all experiments, I do SELECT affyId, AVG(level) AS average FROM Data GROUP BY affyId;
However, I can't figure out how to look for the average expression level of each array probe (affyId) for each experiment... It must be something similar to the last query, but I don't obtain good results... any help?
PD: someone told me I should give some reputation or click to some green button if somebody solves my question... Is it right? How do I do it? I'm pretty new on this website...
This shows the average for every affyId:
SELECT affyId, AVG(level) AS average FROM Data GROUP BY affyId
This the average for every exptId:
SELECT exptId, AVG(level) AS average FROM Data GROUP BY exptId
and this the average for every exptId in every affyId:
SELECT affyId, exptId, AVG(level) AS average FROM Data GROUP BY exptId, affyId
Just add that to the group by clause
SELECT affyId, exptId, AVG(level) AS average
FROM Data
GROUP BY affyId, exptId;

MySQL - How to use GROUP BY / ORDER BY with "nested" dataset?

My (sub)query results in following dataset:
+---------+------------+-----------+
| item_id | version_id | relevance |
+---------+------------+-----------+
| 1 | 1 | 30 |
| 1 | 2 | 30 |
| 2 | 3 | 22 |
| 3 | 4 | 30 |
| 4 | 5 | 18 |
| 3 | 6 | 30 |
| 2 | 7 | 22 |
| 1 | 8 | 30 |
| 5 | 9 | 48 |
| 4 | 10 | 18 |
| 5 | 11 | 48 |
| 3 | 12 | 30 |
| 3 | 13 | 31 |
| 4 | 14 | 19 |
| 2 | 15 | 22 |
| 1 | 16 | 30 |
| 5 | 17 | 49 |
| 2 | 18 | 22 |
+---------+------------+-----------+
18 rows in set (0.00 sec)
Items and versions are stored in separate InnoDB-tables.
Both tables have auto-incrementing primary keys.
Versions have a foreign key to items (item_id).
My question: How do I get a subset based on relevance?
I would like to fetch the following subset containing the most relevant versions:
+---------+------------+-----------+
| item_id | version_id | relevance |
+---------+------------+-----------+
| 1 | 16 | 30 |
| 2 | 18 | 22 |
| 3 | 13 | 31 |
| 4 | 14 | 19 |
| 5 | 17 | 49 |
+---------+------------+-----------+
It would be even more ideal to fetch the MAX(version_id) in case of equal relevance.
I tried grouping, joining, ordering, etcetera in many ways but I'm not able to get the desired result.
Some of the things I tried is:
SELECT item_id, version_id, relevance
FROM (subquery) a
GROUP BY item_id
ORDER BY relevance DESC, version_id DESC
But of course the ordering happens after the fact, so that both relevance and MAX(version_id) information is lost.
Please advice.
This is how you can do this:
SELECT t1.item_id, max(t1.version_id), t1.relevance FROM t t1
LEFT JOIN t t2 ON t1.item_id = t2.item_id AND t1.relevance < t2.relevance
WHERE t2.relevance IS NULL
GROUP BY t1.item_id
ORDER BY t1.item_id, t1.version_id
Output:
| ITEM_ID | VERSION_ID | RELEVANCE |
|---------|------------|-----------|
| 1 | 16 | 30 |
| 2 | 18 | 22 |
| 3 | 13 | 31 |
| 4 | 14 | 19 |
| 5 | 17 | 49 |
Fiddle here.

MySQL order by rand() grouped by day

Is it possible to get random items inside the same day?
For example:
+----+---------------------+
| id | md |
+----+---------------------+
| 1 | 2010-06-27 11:26:01 |
| 2 | 2010-06-27 11:28:20 |
| 3 | 2010-06-27 11:29:46 |
| 4 | 2010-06-27 11:30:50 |
| 5 | 2010-06-27 12:20:56 |
| 6 | 2010-06-27 12:27:42 |
| 7 | 2010-06-27 15:14:05 |
| 8 | 2010-07-06 01:53:33 |
| 9 | 2010-07-06 01:52:52 |
+----+---------------------+
I want to pick random items inside the same day, but at same time i want it ordered by date desc. Something like this:
+----+---------------------+
| id | md |
+----+---------------------+
| 8 | 2010-07-06 01:53:33 | random block
| 9 | 2010-07-06 01:52:52 |
| 2 | 2010-06-27 11:28:20 | random block
| 4 | 2010-06-27 11:30:50 |
| 1 | 2010-06-27 11:26:01 |
| 6 | 2010-06-27 12:27:42 |
| 3 | 2010-06-27 11:29:46 |
| 5 | 2010-06-27 12:20:56 |
| 7 | 2010-06-27 15:14:05 |
+----+---------------------+
No idea how to start or if this is even possible since order by rand() won't accept grouping.
really simple:
SELECT *
FROM tbl
ORDER BY md DESC, RAND()
Probably not very efficient, but try
select * from (select * from tbl order by rand()) as t group by date(md)
If I have understood your question correctly, this should do the trick:
SELECT * FROM table1 ORDER BY DATE(md) DESC, RAND();
Example:
DROP TABLE IF EXISTS `table1`;
CREATE TABLE `table1` (
`id` int(11) NOT NULL auto_increment,
`md` DATETIME,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
DELIMITER //
DROP PROCEDURE IF EXISTS autofill//
CREATE PROCEDURE autofill()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < 50 DO
INSERT INTO table1 (md) VALUES (DATE_ADD(NOW(), INTERVAL FLOOR(RAND() * 1000) HOUR));
SET i = i + 1;
END WHILE;
END;
//
DELIMITER ;
CALL autofill();
SELECT * FROM table1 ORDER BY DATE(md) DESC, RAND();
+----+---------------------+
| id | md |
+----+---------------------+
| 8 | 2010-08-16 13:46:04 |
| 16 | 2010-08-15 19:46:05 |
| 47 | 2010-08-15 18:46:06 |
| 25 | 2010-08-15 15:46:05 |
| 33 | 2010-08-15 09:46:05 |
| 3 | 2010-08-14 20:46:04 |
| 45 | 2010-08-13 03:46:06 |
| 17 | 2010-08-12 13:46:05 |
| 12 | 2010-08-12 06:46:05 |
| 7 | 2010-08-12 15:46:04 |
| 37 | 2010-08-12 14:46:05 |
| 40 | 2010-08-10 05:46:06 |
| 13 | 2010-08-09 10:46:05 |
| 4 | 2010-08-09 00:46:04 |
| 1 | 2010-08-06 12:46:04 |
| 28 | 2010-08-02 23:46:05 |
| 15 | 2010-08-02 10:46:05 |
| 2 | 2010-08-02 01:46:04 |
| 38 | 2010-07-31 13:46:06 |
| 27 | 2010-07-31 04:46:05 |
| 30 | 2010-07-31 03:46:05 |
| 22 | 2010-07-31 08:46:05 |
| 50 | 2010-07-30 05:46:06 |
| 11 | 2010-07-28 13:46:05 |
| 18 | 2010-07-28 21:46:05 |
| 29 | 2010-07-27 23:46:05 |
| 35 | 2010-07-27 11:46:05 |
| 6 | 2010-07-26 20:46:04 |
| 20 | 2010-07-25 03:46:05 |
| 31 | 2010-07-23 07:46:05 |
| 14 | 2010-07-23 23:46:05 |
| 23 | 2010-07-23 10:46:05 |
| 48 | 2010-07-23 17:46:06 |
| 42 | 2010-07-21 03:46:06 |
| 39 | 2010-07-20 05:46:06 |
| 36 | 2010-07-18 05:46:05 |
| 10 | 2010-07-17 01:46:05 |
| 32 | 2010-07-16 06:46:05 |
| 9 | 2010-07-16 15:46:04 |
| 24 | 2010-07-16 10:46:05 |
| 43 | 2010-07-16 09:46:06 |
| 5 | 2010-07-14 01:46:04 |
| 21 | 2010-07-14 08:46:05 |
| 49 | 2010-07-13 07:46:06 |
| 41 | 2010-07-13 15:46:06 |
| 46 | 2010-07-12 04:46:06 |
| 44 | 2010-07-11 16:46:06 |
| 26 | 2010-07-10 14:46:05 |
| 34 | 2010-07-09 16:46:05 |
| 19 | 2010-07-07 01:46:05 |
+----+---------------------+
You can use a WHERE clause...
WHERE date = 'insert date' ORDER BY rand() LIMIT 1`
Then just use PHP to insert whatever the date is into the string there for each date.
Or to use only one MySQL query, simply order them by date descending and pull them all out using PHP...
while ($item = mysql_fetch_array($query)):
// process to figure out the date (I'm sure you can do that)
$mydates[$date][] = $id; // add that ID to that date array
endwhile;
foreach ($mydates as $date):
$key = array_rand($date);
endforeach;