MySQL, Count LIKE statments and oldest date problems - mysql

Fairly new to MySQL and I'm getting a little lost in how to build the following query.
The table below shows what I want my intended output to be like.
+---------+------------+-----------------+-------+----------+------------+
| Account | Inv Date | Description | Value | Inv Item | Eff From |
+---------+------------+-----------------+-------+----------+------------+
| 12 | 2018-08-14 | Unlimited (SV4) | 5.99 | 3056746 | 2018-08-02 |
| 12 | 2018-08-14 | Unlimited (SV4) | 5.99 | 3056748 | 2018-08-02 |
| 15 | 2018-09-14 | Unlimited (GB2) | 7.99 | 3187748 | 2018-09-07 |
| 15 | 2018-09-14 | Unlimited (GB1) | 7.26 | 3187749 | 2018-09-07 |
+---------+------------+-----------------+-------+----------+------------+
I want to see accounts that have more than one description like "Unlimited", the "Inv Date" needs to show only the oldest date for each account. And the "Eff from" needs to be from when the "status" was first "active" on the account.
Here is my code as it currently stands, i've also included the tables i'm trying to join.
SELECT
AA.Account,
MIN(II.InvDate),
ST.Description,
ST.Value,
ST.InvItem,
MIN(AA.EffFrom)
FROM db.tblAccountStatus AA
INNER JOIN db.tblInvoiceID II ON II.Account = AA.Account
INNER JOIN db.tblInvoiceStatus ST ON ST.InvID = II.InvID
WHERE AA.Status = 'Active'
AND ST.Description LIKE '%Unlimited%'
GROUP BY ST.InvItem HAVING COUNT(II.InvDate) >1
.
db.tblInvoiceStatus
+--------+------------------+-------+----------+
| Inv ID | Description | Value | Inv Item |
+--------+------------------+-------+----------+
| 1030 | Unlimited (SV4) | 5.99 | 3056746 |
| 1030 | Unlimited (SV4) | 5.99 | 3056748 |
| 1030 | Extras (PB1) | 0.99 | 3056751 |
| 1045 | Unlimited (SLV2) | 5.99 | 3166769 |
| 1045 | Extras (PA1) | 1.99 | 3166770 |
| 1078 | Unlimited (GB2) | 7.99 | 3187748 |
| 1078 | Unlimited (GB1) | 7.26 | 3187749 |
| 1091 | Unlimited (SV1) | 5.99 | 3186788 |
| 1098 | Unlimited (BA2) | 5.49 | 3209899 |
+--------+------------------+-------+----------+
.
db.tblInvoiceID
+--------+---------+------------+
| Inv ID | Account | Inv Date |
+--------+---------+------------+
| 1030 | 12 | 2018-08-14 |
| 1045 | 12 | 2018-09-14 |
| 1078 | 15 | 2018-09-14 |
| 1091 | 17 | 2018-09-15 |
| 1098 | 17 | 2018-10-15 |
| 1099 | 19 | 2018-10-20 |
+--------+---------+------------+
.
db.tblAccountStatus
+---------+--------+------------+------------+
| Account | Status | Eff From | Eff To |
+---------+--------+------------+------------+
| 12 | Active | 2018-08-02 | 2018-09-16 |
| 12 | Active | 2018-09-17 | 2018-09-28 |
| 12 | Active | 2018-09-29 | NULL |
| 15 | Active | 2018-09-07 | 2018-09-16 |
| 15 | Closed | 2018-09-17 | NULL |
| 17 | Active | 2016-04-28 | NULL |
| 19 | Active | 2015-05-05 | NULL |
+---------+--------+------------+------------+

It seems good to inner join db.tblInvoiceID that has oldest date records as below sql.
SELECT
AA.Account,
II.InvDate,
ST.Description,
ST.Value,
ST.InvItem,
AA.EffFrom
FROM db.tblAccountStatus AA
INNER JOIN (
SELECT InvID, Account, MIN(InvDate) AS InvDate FROM db.tblInvoiceID
GROUP BY Account
) II ON II.Account = AA.Account
INNER JOIN db.tblInvoiceStatus ST ON ST.InvID = II.InvID
WHERE AA.Status = 'Active'
AND ST.Description LIKE '%Unlimited%'
GROUP BY ST.InvItem
The following is my output.
Although your intended output doesn't include Account = 17, I couldn't understand a condition from your question. Please teach me if you have additional conditions.
+---------+------------+------------------+-------+---------+------------+
| Account | InvDate | Description | Value | InvItem | EffFrom |
+---------+------------+------------------+-------+---------+------------+
| 12 | 2018-08-14 | Unlimited (SV4) | 5.99 | 3056746 | 2018-08-02 |
| 12 | 2018-08-14 | Unlimited (SV4) | 5.99 | 3056748 | 2018-08-02 |
| 17 | 2018-09-15 | Unlimited (SV1) | 5.99 | 3186788 | 2016-04-28 |
| 15 | 2018-09-14 | Unlimited (GB2) | 7.99 | 3187748 | 2018-09-07 |
| 15 | 2018-09-14 | Unlimited (GB1) | 7.26 | 3187749 | 2018-09-07 |
+---------+------------+------------------+-------+---------+------------+
5 rows in set (0.00 sec)

Related

Group_Concat() is not working properly in mysql

I have three tables :
em_employee :
emp_number | emp_firstname |
+------------+---------------+
| 1 | Vikram |
| 2 | S. |
| 3 | Gopal |
| 4 | Vaishnavi |
| 5 | Srinivasan |
| 6 | Saravanan
em_project
+------------+------------------------------+
| project_id | name |
+------------+------------------------------+
| 339 | MoneyGram |
| 340 | SERVICE LINE HEAD COMPLIANCE |
| 341 | SERVICE LINE HEAD ANALYTICS |
| 342 | GSI |
| 343 | Tandem |
| 344 | Master Card |
+------------+------------------------------+
em_project_employee:
+------------+------------+
| emp_number | project_id |
+------------+------------+
| 1 | 339 |
| 2 | 340 |
| 3 | 341 |
| 4 | 342 |
| 1 | 343 |
| 6 | 344 |
| 2 | 342 |
+------------+------------+
And I want Output like :
+------------+----------------------------------+
| emp_number | name |
+------------+----------------------------------+
| 1 | MoneyGram , Tandem |
| 2 | SERVICE LINE HEAD COMPLIANCE,GSI |
| 3 | SERVICE LINE HEAD ANALYTICS |
| 4 | GSI |
| 6 | Master Card |
+------------+----------------------------------+
I have tried it with GROUP_CONCAT, but something going wrong. Please help me on this.
Try this query, it produes that output:
SELECT emp_number, GROUP_CONCAT(name) FROM em_project p
INNER JOIN em_project_employee em ON p.project_id = em.project_id
GROUP BY emp_number;
The order of the data will e slightly different from what's in your desired output. If the ordering is important.
GROUP_CONCAT(name ORDER BY p.project_id)

SQL SELECT request using count(*) with multiple GROUP BY

I am currently in an internship and I have to create a missing view, this preventing a website to work perfectly.
This view has to contain multiple informations, but also the number of rows with each couple status/process as in the following:
+----------------+---------+----------+-----------+-----------+--------+
| status | process | project | idprocess | idproject | number |
+----------------+---------+----------+-----------+-----------+--------+
| Not applicable | AP | tms-data | 17 | 2 | 432 |
| Not applicable | AP+51 | tms-data | 18 | 2 | 432 |
| Not applicable | AR | tms-data | 19 | 2 | 432 |
| Realized | AP | tms-data | 17 | 2 | 432 |
| Realized | AP+51 | tms-data | 18 | 2 | 432 |
| Realized | AR | tms-data | 19 | 2 | 432 |
| Safety | AP | tms-data | 17 | 2 | 432 |
| Safety | AP+51 | tms-data | 18 | 2 | 432 |
| Safety | AR | tms-data | 19 | 2 | 432 |
| Ticket | AP | tms-data | 17 | 2 | 432 |
| Ticket | AP+51 | tms-data | 18 | 2 | 432 |
| Ticket | AR | tms-data | 19 | 2 | 432 |
| To be designed | AP | tms-data | 17 | 2 | 432 |
| To be designed | AP+51 | tms-data | 18 | 2 | 432 |
| To be designed | AR | tms-data | 19 | 2 | 432 |
| Validated | AP | tms-data | 17 | 2 | 432 |
| Validated | AP+51 | tms-data | 18 | 2 | 432 |
| Validated | AR | tms-data | 19 | 2 | 432 |
+----------------+---------+----------+-----------+-----------+--------+
18 rows in set (0.03 sec)
I'm using MySQL. I don't understand why it counts this way, any ideas ?
Here is the script I've been using so far :
SELECT alstom_status.name AS status,
alstom_process.name AS process,
alstom_project.name AS project,
alstom_process.idprocess AS idprocess,
alstom_project.idproject AS idproject,
count(*) AS number
FROM alstom_rule INNER JOIN alstom_status ON idstatus
INNER JOIN alstom_project ON idproject
INNER JOIN alstom_process ON idprocess
GROUP BY alstom_status.name, alstom_process.name
ORDER BY process;
This works always for me !
SELECT alstom_status.name AS status,
alstom_process.name AS process,
alstom_project.name AS project,
alstom_process.idprocess AS idprocess,
alstom_project.idproject AS idproject,
count(*) AS number
FROM alstom_rule INNER JOIN alstom_status ON idstatus
INNER JOIN alstom_project ON idproject
INNER JOIN alstom_process ON idprocess
GROUP BY status, process,project,idprocess, idproject;
You may use ( group by alstom_status.name,alstom_process.name,alstom_project.name, alstom_process.idprocess,alstom_project.idproject)

MySQL SUM() returning spurious (?) values

Despite spending an hour on this, the solution is eluding me still. I have a complex-ish query that is returning incorrect data for the SUM(). Yet, when I strip it down to the barest form, it outputs the correct data. But why and fix, I cannot figure out.
The Problem
SELECT po.*, SUM( poo.material_qty ) AS total_items_ordered, suppliers.supplier_name
FROM `purchase_orders` po
LEFT JOIN purchase_orders_items poo ON poo.poid = po.poid
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT
IN (
'Fulfilled', 'Cancelled'
)
AND batch_status NOT
IN (
'Arrived', 'Cancelled', 'Refused', 'Missing', 'Damaged', 'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC
Provides wildly incorrect data for 'total_items_ordered'.
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| poid | date_raised | date_expected | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT | total | userid | DN | manual | po_status | total_items_ordered | supplier_name |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 14850.10 | 2970.02 | 17820.12 | 1 | | N | Raised | 545 | John Parker & Son Ltd |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 997.80 | 199.56 | 1197.36 | 1 | | N | Raised | 80 | John Parker & Son Ltd |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
2 rows in set (0.00 sec)
And yet, when I strip all the complexities out of the query and run the raw SUM(), the value is correct:
mysql> SELECT poid, SUM(material_qty) AS total_items_ordered FROM `purchase_orders_items` GROUP BY poid;
+-------+---------------------+
| poid | total_items_ordered |
+-------+---------------------+
| 15571 | 109 |
| 15572 | 20 |
+-------+---------------------+
2 rows in set (0.00 sec)
Can anyone shed any light on where I'm going wrong here?? I've included all the test table content below just in case you can spot something I've missed. Thank you!
Data Example
mysql> SELECT * FROM purchase_orders;
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| poid | date_raised | date_expected | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT | total | userid | DN | manual | po_status |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 14850.10 | 2970.02 | 17820.12 | 1 | | N | Raised |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 997.80 | 199.56 | 1197.36 | 1 | | N | Raised |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM purchase_orders_items;
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
| poi_id | poid | material_id | material_qty | material_price | material_sku | material_name |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
| 1 | 15571 | 2 | 3 | 100.00 | PKS275282 | 406x140 White Universal Beam (S355) |
| 2 | 15571 | 5 | 10 | 17.40 | 118-64-44 | Test Item (S275) |
| 3 | 15571 | 8 | 1 | 9984.50 | 113-64-21 | A really really really big universal beam (S355) |
| 4 | 15571 | 9 | 77 | 10.00 | 12345 | A thing |
| 5 | 15571 | 10 | 18 | 201.20 | 12-34-56 | 102x230 Narrow Beam (S355) |
| 6 | 15572 | 2 | 6 | 100.00 | PKS275282 | 406x140 White Universal Beam (S355) |
| 7 | 15572 | 5 | 9 | 17.40 | 118-64-44 | Test Item (S275) |
| 8 | 15572 | 9 | 4 | 10.00 | 12345 | A thing |
| 9 | 15572 | 10 | 1 | 201.20 | 12-34-56 | 102x230 Narrow Beam (S355) |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
9 rows in set (0.00 sec)
mysql> SELECT * FROM suppliers;
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
| supplier_id | supplier_name | supplier_telephone | supplier_fax | supplier_added_date | supplier_added_by | supplier_last_updated | supplier_last_updated_by | supplier_assessed | supplier_approved_by |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
| 1 | John Parker & Son Ltd | 01227 783333 | 0800 521932 | 2014-05-04 15:57:43 | 1 | 2014-06-05 16:38:23 | 1 | 2014-05-04 15:57:43 | 2 |
| 2 | Superior Glass Ltd. | 01825 764766 | 01825 767699 | 2014-05-04 17:48:38 | 1 | 2014-06-04 20:14:16 | 1 | 2014-05-04 17:48:38 | 3 |
| 3 | DTS Origins Ltd. | 01283 3283029 | 01928 303494 | 2014-05-04 17:51:57 | 1 | 2014-05-04 17:53:08 | 1 | 2014-05-04 17:51:57 | 2 |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM materials_batch;
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
| material_batch_id | poiid | rcvd_date | purchase_order_no | delivery_note_no | qty | rcvd_by | dn_scanned | material_id | supplier_id | batch_status |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
| 1 | 1 | 0000-00-00 00:00:00 | 15571 | | 3 | 0 | No | 2 | 1 | Ordered |
| 2 | 2 | 0000-00-00 00:00:00 | 15571 | | 10 | 0 | No | 5 | 1 | Ordered |
| 3 | 3 | 0000-00-00 00:00:00 | 15571 | | 1 | 0 | No | 8 | 1 | Ordered |
| 4 | 4 | 0000-00-00 00:00:00 | 15571 | | 77 | 0 | No | 9 | 1 | Ordered |
| 5 | 5 | 0000-00-00 00:00:00 | 15571 | | 18 | 0 | No | 10 | 1 | Ordered |
| 6 | 6 | 0000-00-00 00:00:00 | 15572 | | 6 | 0 | No | 2 | 1 | Ordered |
| 7 | 7 | 0000-00-00 00:00:00 | 15572 | | 9 | 0 | No | 5 | 1 | Ordered |
| 8 | 8 | 0000-00-00 00:00:00 | 15572 | | 4 | 0 | No | 9 | 1 | Ordered |
| 9 | 9 | 0000-00-00 00:00:00 | 15572 | | 1 | 0 | No | 10 | 1 | Ordered |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
The reason for the wrong results should be clear when you leave out the GROUP BY from your query. For each table you JOIN, the number of returned rows is multiplied by the number of rows found by the JOIN.
As the materials_batch table contains multiple entries per order, the resulting total_items_ordered is multiplied by 5 for order number 15571, and its multiplied by 4 for order number 15572.
Try the following:
SELECT
po.*,
(
SELECT SUM(poo.material_qty)
FROM purchase_orders_items poo
WHERE poo.poid = po.poid
) AS total_items_ordered,
suppliers.supplier_name
FROM `purchase_orders` po
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT
IN (
'Fulfilled', 'Cancelled'
)
AND batch_status NOT
IN (
'Arrived', 'Cancelled', 'Refused', 'Missing', 'Damaged', 'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC

MySQL information from another table

I have the following SQL:
Select roleid , deity_level FROM default_jd_deity_role LIMIT 10;
That gives the output:
+--------+-------------+
| roleid | deity_level |
+--------+-------------+
| 1024 | 1 |
| 1043 | 54 |
| 1056 | 1 |
| 1057 | 54 |
| 1072 | 54 |
| 1074 | 45 |
| 1075 | 36 |
| 1088 | 45 |
| 1089 | 45 |
| 1104 | 27 |
+--------+-------------+
Then I have this SQL:
Select roleid , name FROM default_jd_ingame_roles LIMIT 22, 10
That gives the following output:
+--------+---------+
| roleid | name |
+--------+---------+
| 1024 | Hulu |
| 1043 | Cookiez |
| 1056 | Sam |
| 1057 | Sugar |
| 1072 | Leah |
| 1073 | Smexy |
| 1074 | Bam! |
| 1075 | Lexi |
| 1088 | OneShot |
| 1089 | Demono |
+--------+---------+
What I am trying to do is make deity_level add on to the second SQL Query like this:
+--------+---------+-------------+
| roleid | name | deity_level |
+--------+---------+-------------+
| 1024 | Hulu | 1 |
| 1043 | Cookiez | 54 |
| 1056 | Sam | 1 |
| 1057 | Sugar | 54 |
| 1072 | Leah | 54 |
| 1073 | Smexy | 45 |
| 1074 | Bam! | 36 |
| 1075 | Lexi | 45 |
| 1088 | OneShot | 45 |
| 1089 | Demono | 27 |
+--------+---------+-------------+
Try this:
Select a.roleid , a.deity_level, b.name
FROM default_jd_deity_role AS a
JOIN default_jd_ingame_roles AS b ON a.roleid=b.roleid
LIMIT 10
You can achieve this with a JOIN, like this:
SELECT main.roleid, roles.name, main.deity_level
FROM default_jd_deity_role main
LEFT JOIN default_jd_ingame_roles roles ON main.roleid = roles.roleid
LIMIT 22, 10
I'll leave two nice tutorials to get you started on JOINS:
http://www.sitepoint.com/understanding-sql-joins-mysql-database/
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
You are looking for a JOIN query:
SELECT igr.roleid , igr.name, dr.diety_level
FROM default_jd_ingame_roles igr
JOIN default_jd_deity_role dr ON dr.roleid = igr.roleid

mysql group_concat comma separated ids to match names

I wrote this query to find the list of shops selling what categories.
SELECT GROUP_CONCAT(distinct(sub_category_id)) AS s,
vendor_id AS v
FROM link_products_lists_vendors
GROUP BY vendor_id;
This results in,
+---------------------------------------+------------+
| category_ids | vendor_ids |
+---------------------------------------+------------+
| 24,28,25,16,26,23,27,2 | 3 |
| 2 | 67 |
| 19,28,17,16,20,2 | 68 |
| 19,28,24,26,23,21,16,27,22,17,25,2 | 122 |
| 16,2 | 123 |
| 28,17,22,21,18,16,26,27,20,23,25,2 | 124 |
| 22,19,21,20,16,24,28,25,23,26,2 | 125 |
| 23,24,26,25,28,16,20,27,19,2 | 126 |
| 19,26,28,18,20,27,22,16 | 127 |
| 22,26,28,21,23,20,24,19,16,17,27,25,2 | 128 |
| 2 | 129 |
| 2 | 133 |
| 19,20,28,16,27,25,21,23,26,24,22 | 135 |
| 23,28,17,22,26,21,16,20,27,24,25,2 | 136 |
| 19,17,16,21,23,26,22,25,27,20,28 | 137 |
| 19,20,26,22,21,24,23,17,28,16,27,25,2 | 138 |
| 19,20,23,28,26,21,24,16,27,22,25,17,2 | 139 |
| 22,27,20,21,24,17,23,28,26,19,25,2 | 142 |
| 19,28,17,20,2 | 143 |
+---------------------------------------+------------+
19 rows in set (0.01 sec)
What I want now is something like,
+-------------------------- -----------+--- ----------+
| category_names | vendor_names |
+---------------------------------------+--------------+
| mobiles,laptops,desktops | abcShop |
| mobiles | xyzShop |
| desktops,mouses,keyboards | pqrShop |
+---------------------------------------+--------------+
I have the categories table as,
+----+---------------+
| id | name |
+----+---------------+
| 17 | desktops |
| 18 | external_hdds |
| 26 | headphones |
| 27 | headsets |
| 22 | keyboards |
| 16 | laptops |
| 24 | memory_cards |
| 2 | mobile-phones |
| 21 | mouses |
| 25 | pendrives |
| 19 | printers |
| 20 | routers |
| 23 | speakers |
| 28 | tablets |
+----+---------------+
Vendors table as,
+-----+----------------------+
| id | name |
+-----+----------------------+
| 108 | abcShop |
| 109 | xyzShop |
| 45 | pqrShop |
| 89 | . |
| 63 | . |
| 64 | . |
+-----+----------------------+
How should I write a query that will not display ids but use the table that displays ids and displays names? I have no clue from where to start this. Please help!
Just join in the other tables and select those values instead
SELECT GROUP_CONCAT(distinct(c.name)) AS s,
v.name AS v
FROM link_products_lists_vendors l
JOIN categories c on l.category_id = c.id
JOIN vendors v on l.vendor_id = v.id
GROUP BY v.name;
This works as long as vendor names and description names are unique.