Concat into a single row different values of a duplicated ID - mysql

I'm developing a application for library management.
The problem is, I have the following tables: user, employee, loan, book_loan, with them I need a query that returns me an unique
loan's ID, with the user's name, employee's name, book's name, loan's date, devolution's date and status.
I almost did this, but it returns me duplicates of the loan's ID, with the book's name separated by the rows.
These are my tables:
delimiter $$
CREATE TABLE `Loan` (
`id_loan` int(11) NOT NULL AUTO_INCREMENT,
`id_user` int(11) NOT NULL,
`id_employee` int(11) NOT NULL,
`date_loan` date NOT NULL,
`data_devolution` date NOT NULL,
`status` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id_loan`),
KEY `fk_loan_id_user_idx` (`id_user`),
KEY `fk_loan_id_employee` (`id_employee`),
CONSTRAINT `fk_loan_id_employee` FOREIGN KEY (`id_emplyee`) REFERENCES `Employee` (`id_employee`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_loan_id_user` FOREIGN KEY (`id_user`) REFERENCES `User` (`id_user`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8$$
delimiter $$
CREATE TABLE `Employee` (
`id_employee` int(11) NOT NULL AUTO_INCREMENT,
`login` varchar(20) NOT NULL,
`password` varchar(16) NOT NULL,
`level` decimal(10,0) NOT NULL,
PRIMARY KEY (`id_employee`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8$$
delimiter $$
CREATE TABLE `Book` (
`id_book` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(50) NOT NULL,
`id_author` int(11) NOT NULL,
`edition` decimal(10,0) NOT NULL,
`editor` varchar(45) NOT NULL,
`cutter` varchar(12) NOT NULL,
`id_CDU` int(11) NOT NULL,
`status` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id_book`),
KEY `fk_book_id_CDU_idx` (`id_CDU`),
KEY `fk_book_id_author` (`id_author`),
CONSTRAINT `fk_book_id_author` FOREIGN KEY (`id_author`) REFERENCES `Author` (`id_author`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_book_id_CDU` FOREIGN KEY (`id_CDU`) REFERENCES `CDU` (`id_CDU`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8$$
delimiter $$
CREATE TABLE `Book_Loan` (
`id_book` int(11) NOT NULL,
`id_loan` int(11) NOT NULL,
KEY `fk_book_loan_id_loan` (`id_loan`),
KEY `fk_book_loan_id_book` (`id_book`),
CONSTRAINT `fk_book_loan_id_loan` FOREIGN KEY (`id_loan`) REFERENCES `Loan` (`id_loan`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_book_loan_id_book` FOREIGN KEY (`id_book`) REFERENCES `Book` (`id_book`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
delimiter $$
CREATE TABLE `User` (
`id_user` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`address` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
PRIMARY KEY (`id_user`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8$$
This is my query:
SELECT loan.id_loan AS ID,
employee.login AS EMPLOYEE,
user.name AS USER,
book.title AS BOOK,
loan.date_loan AS LOAN,
loan.date_devolution AS DEVOLUTION,
loan.status AS STATUS
FROM Loan loan
INNER JOIN Employee employee ON employee.id_employee = loan.id_employee
INNER JOIN User user ON user.id_user = loan.id_user
INNER JOIN Book_Loan book_loan ON book_loan.id_loan = loan.id_loan
INNER JOIN Book book ON book.id_book = book_loan.id_book;
That returns me e.g.: if the loan has 3 book, which is the maximum:
+-----+-------------+-------------+---------------------------------+------------+------------+--------+
| ID | EMPLOYEE | USER | BOOK | LOAN | DEVOLUTION| STATUS |
+-----+-------------+-------------+---------------------------------+------------+------------+--------+
| 6 | RUBE | John | Book A | 2013-06-22 | 2013-06-29 | 0 |
| 6 | RUBE | John | Book B | 2013-06-22 | 2013-06-29 | 0 |
| 6 | RUBE | John | Book C | 2013-06-22 | 2013-06-29 | 0 |
+-----+-------------+-------------+---------------------------------+------------+------------+--------+
This is what I want:
+-----+-------------+-------------+---------------------------------+------------+------------+--------+
| ID | EMPLOYEE | USER | BOOK | LOAN | DEVOLUTION | STATUS |
+-----+-------------+-------------+---------------------------------+------------+------------+--------+
| 6 | RUBE | John | Book A, Book B, Book C | 2013-06-22 | 2013-06-29 | 0 |
+-----+-------------+-------------+---------------------------------+------------+------------+--------+

Look into using GROUP_CONCAT:
SELECT loan.id_loan AS ID,
employee.login AS EMPLOYEE,
user.name AS USER,
GROUP_CONCAT(book.title) AS BOOK,
loan.date_loan AS LOAN,
loan.date_devolution AS DEVOLUTION,
loan.status AS STATUS
FROM Loan loan
INNER JOIN Employee employee ON employee.id_employee = loan.id_employee
INNER JOIN User user ON user.id_user = loan.id_user
INNER JOIN Book_Loan book_loan ON book_loan.id_loan = loan.id_loan
INNER JOIN Book book ON book.id_book = book_loan.id_book
GROUP BY loan.id_loan

Related

How to speed up MYSQL query with multiple joins?

looking for help to speed up this query:
SELECT tickets.ticketid, datenew, products.name
FROM tickets
INNER JOIN ticketlines ON tickets.id = ticketlines.ticket
INNER JOIN products ON ticketlines.product = products.id
INNER JOIN receipts ON receipts.id = tickets.id
WHERE (category !='feb765ef-c8a8-4fa2-969c-90f67fe6b3be' AND category!='888f4893-f300-43b5-9933-d549ade744e0' AND category !='8f2031e8-64a4-4abf-8175-3d2bedd9f950' AND category !='ca370ced-1c3b-434c-905e-ec1bc709543b' AND category !='f92ff0ac-fa11-4a5f-a3dd-e0d9ed9c171a' AND category !='445e8605-1cd9-4714-b3fd-7389ac29c206' and category !='05143c54-8a7e-4ce2-97cc-f84f9cf41395' AND category !='8c78afea-b9e2-44cf-b497-c384045b3202' AND category !='95919f7f-ff2e-4aa1-8110-ef63c022c01b' AND category !='f4f88b05-38a1-4956-9182-4c04a0808df7') AND datedone IS NULL
ORDER BY ticketid
This is from a cash register database that I am using to pull data for order display. The structure is the receipt has the primary id, the timein and timedone(DATEDONE) timestamps. The ticket table has ticket id which is the same as receipt id. Ticketlines table is the line items on the receipt/ticket. And then Products table has the human readable definitions of the products.
The query is to pull all items that aren't completed, i.e. DATEDONE is null, and display the items that were ordered.
Ticket and Receipt tables have 15K rows, Ticketlines has ~20K rows, Products has 1.5k.
Pretty small data. But this query takes over 20 seconds. I think since I am using primary key IDs for everything, I don't need to index anything, but I am a total noob, so I'm happy to be told I'm wrong. I'll appreciate any help and can provide any further details. Thanks!
EDIT:
per comments, I am showing table structures. I'm sorry for the formatting nightmare, I'm unfamiliar with this platform and unsure how to make it more readable :-(
| receipts | CREATE TABLE `receipts` (
`ID` varchar(255) NOT NULL,
`MONEY` varchar(255) NOT NULL,
`DATENEW` datetime NOT NULL,
`ATTRIBUTES` mediumblob,
`PERSON` varchar(255) DEFAULT NULL,
`DATEDONE` datetime DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `RECEIPTS_FK_MONEY` (`MONEY`),
KEY `RECEIPTS_INX_1` (`DATENEW`),
CONSTRAINT `RECEIPTS_FK_MONEY` FOREIGN KEY (`MONEY`) REFERENCES `closedcash` (`MONEY`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
| tickets | CREATE TABLE `tickets` (
`ID` varchar(255) NOT NULL,
`TICKETTYPE` int(11) NOT NULL DEFAULT '0',
`TICKETID` int(11) NOT NULL,
`PERSON` varchar(255) NOT NULL,
`CUSTOMER` varchar(255) DEFAULT NULL,
`STATUS` int(11) NOT NULL DEFAULT '0',
`DONE` varchar(255) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `TICKETS_FK_2` (`PERSON`),
KEY `TICKETS_CUSTOMERS_FK` (`CUSTOMER`),
KEY `TICKETS_TICKETID` (`TICKETTYPE`,`TICKETID`),
CONSTRAINT `TICKETS_CUSTOMERS_FK` FOREIGN KEY (`CUSTOMER`) REFERENCES `customers` (`ID`),
CONSTRAINT `TICKETS_FK_2` FOREIGN KEY (`PERSON`) REFERENCES `people` (`ID`),
CONSTRAINT `TICKETS_FK_ID` FOREIGN KEY (`ID`) REFERENCES `receipts` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
| ticketlines | CREATE TABLE `ticketlines` (
`TICKET` varchar(255) NOT NULL,
`LINE` int(11) NOT NULL,
`PRODUCT` varchar(255) DEFAULT NULL,
`ATTRIBUTESETINSTANCE_ID` varchar(255) DEFAULT NULL,
`UNITS` double NOT NULL,
`PRICE` double NOT NULL,
`TAXID` varchar(255) NOT NULL,
`ATTRIBUTES` mediumblob,
PRIMARY KEY (`TICKET`,`LINE`),
KEY `TICKETLINES_FK_2` (`PRODUCT`),
KEY `TICKETLINES_ATTSETINST` (`ATTRIBUTESETINSTANCE_ID`),
KEY `TICKETLINES_FK_3` (`TAXID`),
CONSTRAINT `TICKETLINES_ATTSETINST` FOREIGN KEY (`ATTRIBUTESETINSTANCE_ID`) REFERENCES `attributesetinstance` (`ID`),
CONSTRAINT `TICKETLINES_FK_2` FOREIGN KEY (`PRODUCT`) REFERENCES `products` (`ID`),
CONSTRAINT `TICKETLINES_FK_3` FOREIGN KEY (`TAXID`) REFERENCES `taxes` (`ID`),
CONSTRAINT `TICKETLINES_FK_TICKET` FOREIGN KEY (`TICKET`) REFERENCES `tickets` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
| products | CREATE TABLE `products` (
`ID` varchar(255) NOT NULL,
`REFERENCE` varchar(255) NOT NULL,
`CODE` varchar(255) NOT NULL,
`CODETYPE` varchar(255) DEFAULT NULL,
`NAME` varchar(255) NOT NULL,
`PRICEBUY` double NOT NULL,
`PRICESELL` double NOT NULL,
`CATEGORY` varchar(255) NOT NULL,
`TAXCAT` varchar(255) NOT NULL,
`ATTRIBUTESET_ID` varchar(255) DEFAULT NULL,
`STOCKCOST` double DEFAULT NULL,
`STOCKVOLUME` double DEFAULT NULL,
`IMAGE` mediumblob,
`ISCOM` bit(1) NOT NULL DEFAULT b'0',
`ISSCALE` bit(1) NOT NULL DEFAULT b'0',
`ISKITCHEN` bit(1) NOT NULL DEFAULT b'0',
`PRINTKB` bit(1) NOT NULL DEFAULT b'0',
`SENDSTATUS` bit(1) NOT NULL DEFAULT b'0',
`ISSERVICE` bit(1) NOT NULL DEFAULT b'0',
`ATTRIBUTES` mediumblob,
`DISPLAY` varchar(255) DEFAULT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `PRODUCTS_INX_0` (`REFERENCE`),
UNIQUE KEY `PRODUCTS_INX_1` (`CODE`),
UNIQUE KEY `PRODUCTS_NAME_INX` (`NAME`),
KEY `PRODUCTS_FK_1` (`CATEGORY`),
KEY `PRODUCTS_TAXCAT_FK` (`TAXCAT`),
KEY `PRODUCTS_ATTRSET_FK` (`ATTRIBUTESET_ID`),
CONSTRAINT `PRODUCTS_ATTRSET_FK` FOREIGN KEY (`ATTRIBUTESET_ID`) REFERENCES `attributeset` (`ID`),
CONSTRAINT `PRODUCTS_FK_1` FOREIGN KEY (`CATEGORY`) REFERENCES `categories` (`ID`),
CONSTRAINT `PRODUCTS_TAXCAT_FK` FOREIGN KEY (`TAXCAT`) REFERENCES `taxcategories` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
Also, here is EXPLAIN output:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------+------------+--------+--------------------------+---------+---------+------------------------------------+-------+----------+----------------------------------------------+
| 1 | SIMPLE | receipts | NULL | ALL | PRIMARY | NULL | NULL | NULL | 14624 | 10.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | tickets | NULL | eq_ref | PRIMARY | PRIMARY | 767 | receipts.ID | 1 | 100.00 | NULL |
| 1 | SIMPLE | ticketlines | NULL | ref | PRIMARY,TICKETLINES_FK_2 | PRIMARY | 767 | receipts.ID | 1 | 100.00 | Using where |
| 1 | SIMPLE | products | NULL | eq_ref | PRIMARY,PRODUCTS_FK_1 | PRIMARY | 767 | ticketlines.PRODUCT | 1 | 97.97 | Using where |
+----+-------------+-------------+------------+--------+--------------------------+---------+---------+------------------------------------+-------+----------+----------------------------------------------+
4 rows in set, 1 warning (0.04 sec)
Try changing data types of all columns to the minimal required ones.
Add indexes on columns in WHERE.
Add index on ticketlines.ticket.
I ended up deleted 10K rows from every linked table and it queries running in .2 seconds now. I guess absent any more advice, i will be doing annual cleanup of old tickets.

LEFT JOIN / IS NULL not working as expected -to select only row which is not in another table

I am trying to select rows which is not in another table. Here I have used LEFT JOIN with IS NULL, but not getting expected result. It works only one for table, but not in another table.
Mainly I Can't manage the relation between four tables. fee - that includes fee categories) and fee_tm - includes lists of month to pay fee), cls_fee - fee criteria of each classes) and invoice - contains information about paid fee).
And in result I am trying to show student lists who haven't paid, or those students records which is not in invoice table.
Mysql
SELECT
fee_tm.id AS ftm_d,
fee.id AS f_id,
fee_tm.en_ttl AS f_tm,
fee.en_ttl AS fee,
cls_fee.fee AS f_mnt
FROM
fee
LEFT JOIN
fee_tm ON fee_tm.year = fee.year
LEFT JOIN
cls_fee ON cls_fee.fee_id = fee.id
LEFT JOIN
student ON student.cls = cls_fee.c_id AND student.sec = cls_fee.s_id
LEFT JOIN
invoice ON invoice.stu_id = student.id AND invoice.fee_id = fee.id AND invoice.ftm_id = fee_tm.id
WHERE
student.id =1 AND invoice.ftm_id is NULL AND invoice.fee_id is NULL
Current Result
ftm_d | f_id | f_tm | fee | f_mnt
=====================================================
2 | 1 | Feb | Annual | 1000
2 | 2 | Feb | Monthly | 560
Expected Result
ftm_d | f_id | f_tm | fee | f_mnt
=====================================================
2 | 2 | Feb | Monthly | 560
My result is checking only f_tm column, so in my current result month Jan is filtered, but it has to check the fee column also and the Annual row has to be filtered.
So, we can know the students who haven't paid their fee. If the record is found in invoice table, then this fee category should be filtered in result.
Database Structure
Student
id | en_ttl | cls | sec | year
========================================
1 | John | 1 | 1 | 1
cls
id | en_ttl | year
========================
1 | One | 1
sec
id | en_ttl | year
========================
1 | A | 1
fee
id | en_ttl | year
========================
1 | Annual | 1
2 | Monthly | 1
3 | Library | 1
fee_tm
id | en_ttl | year
========================
1 | Jan | 1
2 | Feb | 1
cls_fee
id | c_id | s_id | fee_id | fee
===============================================
1 | 1 | 1 | 1 | 1000
2 | 1 | 1 | 2 | 560
invoice
id | stu_id | fee_id | ftm_id
======================================
1 | 1 | 1 | 1
DDL Statements of tables
CREATE TABLE `student` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`en_ttl` varchar(100) NOT NULL,
`cls` int(2) NOT NULL,
`sec` int(2) NOT NULL,
`year` int(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
CREATE TABLE `cls` (
`id` int(2) NOT NULL AUTO_INCREMENT,
`en_ttl` varchar(50) NOT NULL,
`year` int(2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
CREATE TABLE `sec` (
`id` int(2) NOT NULL AUTO_INCREMENT,
`en_ttl` varchar(50) NOT NULL,
`year` int(2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
CREATE TABLE `fee` (
`id` int(2) NOT NULL AUTO_INCREMENT,
`en_ttl` varchar(50) NOT NULL,
`year` int(2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
CREATE TABLE `fee_tm` (
`id` int(2) NOT NULL AUTO_INCREMENT,
`en_ttl` varchar(50) NOT NULL,
`year` int(2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
CREATE TABLE `cls_fee` (
`id` int(2) NOT NULL AUTO_INCREMENT,
`c_id` int(2) NOT NULL,
`s_id` int(2) NOT NULL,
`fee_id` int(2) NOT NULL,
`fee` int(6) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `fee` (`c_id`,`s_id`,`fee_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
CREATE TABLE `invoice` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`stu_id` int(4) NOT NULL,
`fee_id` int(11) NOT NULL,
`ftm_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
use studentid=1 in on cluase
SELECT
fee_tm.id AS ftm_d,
fee.id AS f_id,
fee_tm.en_ttl AS f_tm,
fee.en_ttl AS fee,
cls_fee.fee AS f_mnt
FROM
fee
inner JOIN
fee_tm ON fee_tm.year = fee.year and fee.id=fee_tm.id inner join cls_fee on cls_fee.fee_id = fee.id
LEFT JOIN
student ON student.cls = cls_fee.c_id AND student.sec = cls_fee.s_id
left join invoice ON invoice.stu_id = student.id AND invoice.fee_id = fee.id AND invoice.ftm_id = fee_tm.id and student.id=1
where invoice.fee_id is null

Modify child record (update modified_date and is_delete) when parents' respective values are changed

My question is in reference to this question.
Say I have three tables, user, country and user_activity whose schema/table-structure are given below:-
|---------------------------------------------|
| id | fname | lname | status |
|---------------------------------------------|
country:-
|--------------------------------|
| id | name | status |
|--------------------------------|
user_activity
|-------------------------------------------------------------------------|
| id | user_id | activity_type | country_id | location | status |
|-------------------------------------------------------------------------|
Say, I create the user table like this:-
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`fname` varchar(255) NOT NULL,
`lname` varchar(255) NOT NULL,
`status` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `iduser` (`id`,`status`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
Then, I create the country table like this:-
CREATE TABLE `country` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`status` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `idcountry` (`id`,`status`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
I want to create a table user_activity where the status of user_activity record would change according to the status of user if user_activity.user_id matches user.id
At the same time, if status of user_activity record would change according to the status of country if user_activity.country_id matches country.id.
How can I do that? How can I achieve the objective at the database level, instead of setting it via PHP scripting?

mysql sum with group by query need specific sum

Run code in http://rextester.com/OZKM95674
I am trying to come up with an fast and easy way to get the sum of quantity for all variations of an item but also include data such as all tags (comma seperated) and one of the images for an item (doesn't matter which one). There are many tables involve shown below:
Query 1: This query below gets the data I want for quantity but is missing data I need for my application (see query 2).
SELECT phppos_items.item_id,
phppos_items.name,
SUM(phppos_location_item_variations.quantity) as quantity
FROM `phppos_items`
LEFT JOIN `phppos_item_variations`
ON `phppos_item_variations`.`item_id` = `phppos_items`.`item_id`
LEFT JOIN `phppos_location_item_variations`
ON `phppos_location_item_variations`.`item_variation_id` = `phppos_item_variations`.`id`
and `phppos_location_item_variations`.`location_id` = 1
GROUP BY `phppos_items`.`item_id`
Result:
+---------+------+----------+
| item_id | name | quantity |
+---------+------+----------+
| 1 | TEST | 10 |
+---------+------+----------+
Query 2: But in the application I actually need more data about an item such as tags and one image (could be many just need one). I need the exact output as below but instead of the quantity being 60 I need it to be 20 like before. I know the reason this is happening because when I do group by; there is more than one row because there are 3 tags and 1 image.
SELECT phppos_items.item_id,
phppos_items.name, SUM(phppos_location_item_variations.quantity) as quantity,
`phppos_item_images`.`image_id` as `image_id`,
GROUP_CONCAT(DISTINCT phppos_tags.name) as tags
FROM `phppos_items`
LEFT JOIN `phppos_item_variations`
ON `phppos_item_variations`.`item_id` = `phppos_items`.`item_id`
LEFT JOIN `phppos_location_item_variations`
ON `phppos_location_item_variations`.`item_variation_id` = `phppos_item_variations`.`id`
and `phppos_location_item_variations`.`location_id` = 1
LEFT JOIN `phppos_items_tags`
ON `phppos_items_tags`.`item_id` = `phppos_items`.`item_id`
LEFT JOIN `phppos_tags`
ON `phppos_tags`.`id` = `phppos_items_tags`.`tag_id`
LEFT JOIN `phppos_item_images`
ON `phppos_items`.`item_id` = `phppos_item_images`.`item_id`
WHERE `phppos_items`.`deleted` = 0
AND `phppos_items`.`system_item` = 0
GROUP BY `phppos_items`.`item_id`
+---------+------+----------+----------+--------------------+
| item_id | name | quantity | image_id | tags |
+---------+------+----------+----------+--------------------+
| 1 | TEST | 60 | 1 | test,test 2,test 3 |
+---------+------+----------+----------+--------------------+
What is an efficient way to get all this data in one query?
Sample data:
phppos_items:
+---------+------+
| item_id | name |
+---------+------+
| 1 | TEST |
+---------+------+
phppos_item_variations:
+---------+----+
| item_id | id |
+---------+----+
| 1 | 1 |
+---------+----+
phppos_location_item_variations:
+-------------------+----------+
| item_variation_id | quantity |
+-------------------+----------+
| 1 | 10 |
+-------------------+----------+
phppos_tags:
+--------+----+
| name | id |
+--------+----+
| test | 1 |
| test 2 | 2 |
| test 3 | 3 |
+--------+----+
phppos_items_tags:
+---------+--------+
| item_id | tag_id |
+---------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
+---------+--------+
phppos_item_images:
+---------+----------+
| item_id | image_id |
+---------+----------+
| 1 | 1 |
| 1 | 4 |
+---------+----------+
Tables involved
CREATE TABLE `phppos_items` (
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`item_id` int(10) NOT NULL AUTO_INCREMENT,
`deleted` int(1) NOT NULL DEFAULT '0',
`system_item` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`item_id`),
UNIQUE KEY `item_number` (`item_number`),
KEY `deleted` (`deleted`),
KEY `deleted_system_item` (`deleted`,`system_item`),
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
CREATE TABLE `phppos_item_variations` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`item_id` int(10) NOT NULL,
PRIMARY KEY (`id`),
KEY `phppos_item_variations_ibfk_1` (`item_id`),
CONSTRAINT `phppos_item_variations_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `phppos_items` (`item_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
CREATE TABLE `phppos_location_item_variations` (
`item_variation_id` int(10) NOT NULL,
`location_id` int(10) NOT NULL,
`quantity` int(1) DEFAULT NULL,
`reorder_level` decimal(23,10) DEFAULT NULL,
`replenish_level` decimal(23,10) DEFAULT NULL,
PRIMARY KEY (`item_variation_id`,`location_id`),
KEY `phppos_item_attribute_location_values_ibfk_2` (`location_id`),
CONSTRAINT `phppos_item_attribute_location_values_ibfk_1` FOREIGN KEY (`item_variation_id`) REFERENCES `phppos_item_variations` (`id`),
CONSTRAINT `phppos_item_attribute_location_values_ibfk_2` FOREIGN KEY (`location_id`) REFERENCES `phppos_locations` (`location_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
CREATE TABLE `phppos_items_tags` (
`item_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
PRIMARY KEY (`item_id`,`tag_id`),
KEY `phppos_items_tags_ibfk_2` (`tag_id`),
CONSTRAINT `phppos_items_tags_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `phppos_items` (`item_id`),
CONSTRAINT `phppos_items_tags_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `phppos_tags` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
CREATE TABLE `phppos_tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ecommerce_tag_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`last_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`deleted` int(1) NOT NULL DEFAULT '0',
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `tag_name` (`name`),
KEY `deleted` (`deleted`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
CREATE TABLE `phppos_item_images` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`alt_text` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`item_id` int(11) DEFAULT NULL,
`item_variation_id` int(10) DEFAULT NULL,
`ecommerce_image_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`image_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `phppos_item_images_ibfk_1` (`item_id`),
KEY `phppos_item_images_ibfk_2` (`image_id`),
KEY `phppos_item_images_ibfk_3` (`item_variation_id`),
CONSTRAINT `phppos_item_images_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `phppos_items` (`item_id`),
CONSTRAINT `phppos_item_images_ibfk_2` FOREIGN KEY (`image_id`) REFERENCES `phppos_app_files` (`file_id`),
CONSTRAINT `phppos_item_images_ibfk_3` FOREIGN KEY (`item_variation_id`) REFERENCES `phppos_item_variations` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
You said your first query already works so now you need get the remaining information
SQL DEMO
SELECT Q1.*, Q2.tags, Q3.image_id
FROM ( SELECT phppos_items.item_id,
phppos_items.name,
SUM(phppos_location_item_variations.quantity) as quantity
FROM `phppos_items`
LEFT JOIN `phppos_item_variations`
ON `phppos_item_variations`.`item_id` = `phppos_items`.`item_id`
LEFT JOIN `phppos_location_item_variations`
ON `phppos_location_item_variations`.`item_variation_id` = `phppos_item_variations`.`id`
and `phppos_location_item_variations`.`location_id` = 1
GROUP BY `phppos_items`.`item_id` ) as Q1
LEFT JOIN ( SELECT i.item_id,
GROUP_CONCAT(DISTINCT t.name) as tags
FROM phppos_items i
LEFT JOIN phppos_items_tags it
ON i.item_id = it.item_id
LEFT JOIN phppos_tags t
ON it.tag_id = t.id
GROUP BY i.item_id
) as Q2
ON Q1.item_id = Q2.item_id
LEFT JOIN ( SELECT item_id, MIN(image_id) as image_id
FROM phppos_item_images
GROUP BY item_id
) as Q3
ON Q1.item_id = Q3.item_id
OUTPUT

MySQL Multiple COUNT in the same table in a single request

I need some help with my SQL request. I have this table:
CREATE TABLE `contact` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(65) DEFAULT NULL,
`last_name` varchar(65) DEFAULT NULL,
`phonenumber` varchar(45) NOT NULL,
`avinumber` varchar(45) DEFAULT NULL,
`date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`source` varchar(45) NOT NULL,
`nbrtryies` int(11) NOT NULL DEFAULT '0',
`treaty_at` date DEFAULT NULL,
`comment` varchar(255) DEFAULT '',
`status` varchar(45) DEFAULT 'KO',
`campagne_id` int(11) NOT NULL,
`treated_by` int(11) DEFAULT NULL,
`nodetree_id` int(11) DEFAULT NULL,
`avi` varchar(45) DEFAULT NULL,
`sessionid` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `fk_contact_campagne1_idx` (`campagne_id`),
KEY `fk_contact_agent1_idx` (`treated_by`),
CONSTRAINT `fk_contact_agent` FOREIGN KEY (`treated_by`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_contact_campagne1` FOREIGN KEY (`campagne_id`) REFERENCES `campagne` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=82 DEFAULT CHARSET=latin1;
I need to count the number of the rows and the number of the rows when the column:
treated_by
has a certain value and group the result by that column
Thsi is what I did but I doesn't seem to work:
SELECT
co.treated_by AS userId,
COUNT(*) AS treated,
SUM(CASE WHEN ca.userId=1 THEN 1 ELSE 0 END) AS total
FROM
contact AS co
INNER JOIN
campagne AS ca ON ca.id = co.campagne_id
WHERE
(co.date BETWEEN '2013-07-09' AND '2014-08-15')
AND co.treated_by IN (2 , 40)
GROUP BY co.treated_by
This is what I got:
----------------------------
| userId | treated | total |
----------------------------
| 2 | 5 | 5 |
----------------------------
| 40 | 3 | 3 |
----------------------------
And I need something like:
----------------------------
| userId | treated | total |
----------------------------
| 2 | 5 | 20 |
----------------------------
| 40 | 3 | 20 |
----------------------------
Thanks a lot for your help
GROUP BY co.treated_by , It produces record COUNT(*) AS treated 5 and 3 , so SUM(CASE WHEN ca.userId=1 THEN 1 ELSE 0 END) AS total , It is impossible much than 20 and 20.
If the condition is on co.treated_by, then why does the logic contain ca.userId?
Perhaps this will work:
SELECT co.treated_by AS userId,
COUNT(*) AS treated,
SUM(co.treated_by) AS total
FROM contact co INNER JOIN
campagne ca
ON ca.id = co.campagne_id
WHERE (co.date BETWEEN '2013-07-09' AND '2014-08-15') AND
co.treated_by IN (2 , 40)
GROUP BY co.treated_by;
Note that I also replaced the calculation for total with a simpler version supported by MySQL.