select value from another table - mysql - mysql

I have 2 tables "srot_data" and "vada"
CREATE TABLE `vada`
(
`id` INT(10) NOT NULL,
`cislo` INT(10) DEFAULT NULL,
`popis` VARCHAR(50) DEFAULT NULL
)
engine=innodb
DEFAULT charset=utf8;
CREATE TABLE `srot_data`
(
`id` INT(10) NOT NULL,
`vada` INT(10) DEFAULT NULL
);
INSERT INTO `srot_data` (`ID`, `Datum`, `ID_obsluha`, `Linka`, `Kontejner`, `Vada`, `m_srot`, `m_pres`, `blok`) VALUES (1, '2018-04-16 11:23:44', 21, 'EXMET2', 'ELDY-', 18, '27.500', '12.500', 1),(2, '2018-04-16 12:18:06', 21, 'EXMET2', 'ELDY-', 5, '1.000', '0.000', NULL);
INSERT INTO `vada` (`ID`, `Cislo`, `Popis`) VALUES(1, 1, 'Najíždění výroby(resp. nové elektrody)'),(2, 2, 'Expander - poškozená mřížka'),(3, 3, 'Olověný pás - koroze '),(4, 4, 'Olověný pás - potrhaná mřížka'),(5, 5, 'Pastovačka - nedopastované elektrody');
Vada from srot_data = ID from vada. And I need to get Popis from table vada.
My sql is:
$sql = "SELECT count(blok) AS Total ,
Vada AS vada
FROM srot_data
LEFT JOIN vada ON vada.Popis = srot_data.Vada
WHERE Linka = 'EXMET1'
GROUP BY vada
ORDER BY Total DESC limit 1";
but it doesn´t work. I'm getting a number (vada from table srot_data). But not getting a text value from Popis (from table vada).
{"Total":"37", "vada":"5".}
And I need
{"Total":"37", "vada":"Pastovačka - nedopastované elektrody".}
Linka and blok are not important for this problem, so I deleted it from tabel for this time.

Related

MySQL query not acting as expected

I am trying to get all bills that have NOT been FULLY paid.
I have three tables that are needed for this.
Table 1 - billInvoiceMain
biId - unique ID
userId - users ID
type - bill or invoice
userItemId - unique ID that user chooses for their records
Table 2 - billInvoiceDetail
biId - references unique ID in billInvoiceMain
quantity
price
Table 3 - transaction
transactionId - unique ID
userId - users ID
biId - references id in billInvoiceMain
paymentAmount
So a user enters bills, and then once they make a payment (multiple smaller payments could be made on a bill until it reaches the full amount or they could make a single payment for the whole amount) they enter it and it gets saved in the transaction table.
Here is a SQL Fiddle that has abbreviated versions of test data.
CREATE TABLE IF NOT EXISTS `billInvoiceDetail` (
`biId` int(15) NOT NULL,
`productId` int(15) DEFAULT NULL,
`accountId` int(15) DEFAULT NULL,
`description` varchar(2000) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`quantity` decimal(20,3) NOT NULL,
`price` decimal(20,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `billInvoiceDetail` (`biId`, `productId`, `accountId`, `description`, `quantity`, `price`) VALUES
(51, NULL, 7, 'Pylaisiella steerei Ando & Higuchi', 4.000, 19.65),
(51, NULL, 11, 'Rubus insons L.H. Bailey', 1.000, 10.17),
(99, NULL, 11, 'Leontodon hispidus L.', 3.000, 11.99),
(99, NULL, 7, 'Peltophorum (T. Vogel) Benth.', 5.000, 33.76),
(100, NULL, 8, 'Scleria P.J. Bergius', 1.000, 10.55),
(100, NULL, 12, 'Gilia ochroleuca M.E. Jones ssp. exilis (A. Gray) A.D. Grant & V.E. Grant', 2.000, 42.54);
CREATE TABLE IF NOT EXISTS `billInvoiceMain` (
`biId` int(15) NOT NULL,
`userId` int(15) NOT NULL,
`type` varchar(7) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`cvId` int(15) NOT NULL,
`startDate` date DEFAULT NULL,
`dueDate` date DEFAULT NULL,
`userItemId` varchar(25) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `billInvoiceMain` (`biId`, `userId`, `type`, `cvId`, `startDate`, `dueDate`, `userItemId`) VALUES
(51, 1, 'bill', 17, '2021-01-01', '2021-01-31', '53396841'),
(99, 1, 'bill', 28, '2021-01-01', '2021-01-31', '16269083'),
(100, 1, 'bill', 28, '2021-01-07', '2021-01-17', '03200283');
CREATE TABLE IF NOT EXISTS `transaction` (
`transactionId` int(15) NOT NULL,
`userId` int(15) NOT NULL,
`biId` int(15) NOT NULL,
`paymentDate` date NOT NULL,
`paymentMethod` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`accountId` int(15) NOT NULL,
`paymentAmount` decimal(20,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `transaction` (`transactionId`, `userId`, `biId`, `paymentDate`, `paymentMethod`, `accountId`, `paymentAmount`) VALUES
(51, 1, 51, '2021-01-04', 'Check', 1, 78.60),
(52, 1, 51, '2021-01-19', 'Credit Card', 3, 10.17),
(53, 1, 99, '2021-01-14', 'Check', 1, 10.00);
SELECT billInvoiceMain.biId, SUM(transaction.paymentAmount), billInvoiceMain.useritemid
FROM billInvoiceMain
INNER JOIN transaction ON billInvoiceMain.biId = transaction.biId
WHERE billInvoiceMain.userId = 1 AND billInvoiceMain.type = 'bill'
GROUP BY billInvoiceMain.biId;
SELECT ROUND(ABS(SUM(billInvoiceDetail.price *billInvoiceDetail.quantity)),2)
FROM billInvoiceDetail
INNER JOIN billInvoiceMain ON billInvoiceDetail.biId = billInvoiceMain.biId
WHERE billInvoiceMain.userId=1 AND billInvoiceMain.type = 'bill'
GROUP BY billInvoiceMain.biId;
SELECT billInvoiceMain.biId, billInvoiceMain.useritemid
FROM billInvoiceMain
INNER JOIN transaction ON billInvoiceMain.biId = transaction.biId
INNER JOIN billInvoiceDetail ON billInvoiceDetail.biId = transaction.biId
WHERE billInvoiceMain.userId = 1 AND billInvoiceMain.type = 'bill'
HAVING SUM(transaction.paymentAmount) != ROUND(ABS(SUM(billInvoiceDetail.price *billInvoiceDetail.quantity)),2);
The first query allows me to sum of all the payments from transaction grouped by bill id.
The second query sums all the bills.
The third query I tried combing the two. However, when I try to use a GROUP BY, it gives an error. So, I got rid of that and now it just returns the first bill even if it has been paid.
Desired Results (retrieves the biId and userItemId of all bills that have not been fully paid based on the transaction table):
biId
userItemId
99
16269083
100
03200283
I have spent a lot of time trying to figure this out but am lost.
The following query retrieves rows that don't match the biId obtained by joining the result of sum of all the payments from transaction grouped by bill id and the result of sum of all the bills from billInvoiceDetail grouped by bill id.
SELECT biId, useritemid FROM billInvoiceMain
WHERE userId = 1 AND type = 'bill'
AND biId NOT IN(
SELECT t.biId FROM
(SELECT biId,SUM(paymentAmount) pay FROM transaction GROUP BY biId) t
INNER JOIN
(SELECT biId,ROUND(ABS(SUM(price*quantity)),2) bill FROM billInvoiceDetail GROUP BY biId) d
ON t.biId=d.biId AND t.pay=d.bill
)
SQL Fiddle

Complicated query to get opening balance, added_qty, reduced_qty and ending balance for a specific period

I am trying to figure out a way to get opening balance, added_qty, reduced_qty and ending balance
for a specific period with 1 mysql query.
I have the following tables:
Explanations for Table Loadings
FIELD loading_type has the following meanings:
1 - initial loading / first time product qty added
2 - additional loading / added additional qty
3 - reduced qty / could be various reasons, for example reduced by order, than order_id > 0 | reduced becaused missing | reduced because broken
The next important thing here is that reduced by order qty must be taken only if paid_date from TABLE orders has date between given period
PLEASE NOTE that row #3 from Table Loadings was not taken in the expected results as reduce_qty because its order paid_date is in January next year so that's why its being counted in reduce_qty for January
and
The expected results should look like:
or if you change the period to
or if you change the period to
I have prepared a dump for sample databases as following:
--
-- Table structure for table `Loadings`
--
DROP TABLE IF EXISTS `Loadings`;
CREATE TABLE `Loadings` (
`id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`added_qty` int(11) NOT NULL DEFAULT 0,
`reduce_qty` int(11) NOT NULL DEFAULT 0,
`loading_type` int(1) NOT NULL DEFAULT 1,
`order_id` int(11) NOT NULL DEFAULT 0,
`added_date` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `Loadings` VALUES(1, 4, 3, 0, 1, 0, '2020-12-03 08:46:40');
INSERT INTO `Loadings` VALUES(2, 4, 1, 0, 2, 0, '2020-12-15 08:46:40');
INSERT INTO `Loadings` VALUES(3, 4, 0, 1, 3, 1, '2020-12-16 08:46:40');
INSERT INTO `Loadings` VALUES(4, 4, 0, 2, 3, 2, '2020-12-21 08:46:40');
INSERT INTO `Loadings` VALUES(5, 4, 2, 0, 2, 0, '2021-01-05 08:46:40');
INSERT INTO `Loadings` VALUES(6, 4, 0, 1, 3, 3, '2021-01-06 08:46:40');
ALTER TABLE `Loadings` ADD PRIMARY KEY (`id`);
ALTER TABLE `Loadings` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
COMMIT;
--
-- Table structure for table `demo_orders`
--
CREATE TABLE `demo_orders` (
`id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`order_status` varchar(20) NOT NULL,
`paid_date` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `demo_orders` VALUES(1, 4, 'finished', '2021-01-05 08:46:40');
INSERT INTO `demo_orders` VALUES(2, 4, 'finished', '2020-12-22 08:46:40');
INSERT INTO `demo_orders` VALUES(3, 4, 'finished', '2021-01-05 08:46:40');
ALTER TABLE `demo_orders` ADD PRIMARY KEY (`id`);
ALTER TABLE `demo_orders` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
COMMIT;
So far I started with this query:
select concat("Opening balance: ",
sum(added_qty-reduce_qty)) as opening from Loadings where product_id = "4" and
month(added_date) = month( date_sub("2021-02-01", interval day("2021-02-01")+1 day) ) and
year(added_date) = year( date_sub("2021-02-01", interval day("2021-02-01")+1 day) )
union all select concat("Debit: ", sum(reduce_qty)) as debit from Loadings where product_id = "4" and
month(added_date) = month( date_sub("2021-02-01", interval day("2021-02-01")+1 day) ) and
year(added_date) = year( date_sub("2021-02-01", interval day("2021-02-01")+1 day) )
union all select concat("Credit: ", sum(added_qty)) as credit from Loadings where product_id = "4" and
month(added_date) = month( date_sub("2021-02-01", interval day("2021-02-01")+1 day) ) and
year(added_date) = year( date_sub("2021-02-01", interval day("2021-02-01")+1 day) );
but the customer added a requirement that orders that not paid between the period date must not counted and this totally confused me how the query should looks like..
AT this point the above query seems very poor approach but I added because #Shadow suggested to demponstrate some query attempt..
Any help highly appreciated !

Calculating three differents sum in three tables

I have these tables:
DROP TABLE IF EXISTS books;
CREATE TABLE `books` (
`bookId` mediumint(8) UNSIGNED NOT NULL,
`title` varchar(10) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `books`
ADD PRIMARY KEY (`bookId`),
DROP TABLE IF EXISTS movements;
CREATE TABLE `movements` (
`movementId` mediumint(8) UNSIGNED NOT NULL,
`movementTypeId` tinyint(3) UNSIGNED NOT NULL,
`deletedFlag` tinyint(3) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `movements`
ADD PRIMARY KEY (`movementId`),
ADD KEY `movementId` (`movementTypeId`,`deletedFlag`) USING BTREE;
DROP TABLE IF EXISTS movements_types;
CREATE TABLE `movements_types` (
`movementTypeId` mediumint(8) UNSIGNED NOT NULL,
`title` varchar(200) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `movements_types`
ADD PRIMARY KEY (`movementTypeId`);
DROP TABLE IF EXISTS movements_books;
CREATE TABLE `movements_books` (
`movementId` mediumint(8) UNSIGNED NOT NULL,
`bookId` mediumint(8) UNSIGNED NOT NULL,
`bookSize` tinyint(3) UNSIGNED NOT NULL,
`quantity` smallint(5) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `books` (`bookId`, `title`) VALUES
(1, 'Harry Potter'),
(2, 'Mysql Join'),
(3, 'Comedy');
INSERT INTO `movements` (`movementId`, `movementTypeId`, `deletedFlag`) VALUES
(7, 1, 0),
(8, 2, 0),
(9, 2, 0);
INSERT INTO `movements_types` (`movementTypeId`, `title`) VALUES
(1, "Bought"),
(2, "Sold");
INSERT INTO `movements_books` (`movementId`, `bookId`, `bookSize`, `quantity`) VALUES
(7, 1, 1, 3),
(7, 1, 2, 3),
(7, 2, 1, 3),
(7, 2, 2, 3),
(8, 1, 1, 2),
(8, 1, 1, 2),
(9, 2, 1, 3);
bookSize is just an integer indicating the size of the book.
movements_books actually has 111824 records, movements has 4534.
deletedFlag is 1 for a deleted movement (I prefer to keep them flagged) and 0 otherwise.
I need help creating indexes and I need these results:
1) sizes sold/bought/available for each book (bookId, bookSize, booksSold, booksBought, booksBought minus booksSold)
2) books sold/bought/available for each book of all size (bookId, booksSold, booksBought, booksBought minus booksSold)
To get the one of the statistics I tried:
SELECT
books.title
movements_books_grouped.bookId,
SUM(IF(movements.movementTypeId=1, movements_books_grouped.quantity, NULL)) AS booksBought,
SUM(IF(movements.movementTypeId=2, movements_books_grouped.quantity, NULL)) AS booksSold,
(
SUM(IF(movements.movementTypeId=1, movements_books_grouped.quantity, 0))-
SUM(IF(movements.movementTypeId=2, movements_books_grouped.quantity, 0))
) AS booksAvailability,
FROM
(
SELECT bookId,quantity,movementId FROM movements_books GROUP BY bookId
) AS movements_books_grouped
JOIN movements ON movements.movementId=movements_books_grouped.movementId
JOIN books ON books.bookId=movements_books_grouped.bookId
GROUP BY movements_books_grouped.bookId
ORDER BY book.title
but it's very slow.
Edit: I needed to add another table to the example because that's the one that makes really slow the last query. I need to join to this table because I need to order the result by title.
Here's a query that can use indexes:
SELECT m.movementId
, m.movementTypeId
, m.deletedFlag
, mb.bookId
, mb.bookSize
, t.title
FROM movements m
JOIN movements_types t
ON t.movementTypeId = m.movementTypeId
JOIN movements_books mb
ON mb.movementid = m.movementid
WHERE m.deletedFlag=0;
An index on (m.movementTypeId, m.deletedFlag) may prove beneficial, but best to suck it and see.

SQL - how to get all subcategory products incl. self products

I have a problem with my database and I hope you can help me with this.
I have tables like this:
categories
--------------------
|id | name | parent|
____________________
categories_x_products (m:n)
---------------------
|id | ctg_id | p_id |
---------------------
products
------------
| id, name |
------------
And my question is: "how to get all my & subcategories product count?"
For example:
categories:
id = 1, name = computers, parent = 0 (1 product)
id = 2, name = notebooks, parent = 1 (2 products)
and I want to get
computers : 3
notebooks : 2
I try this but does not working
select a.name, count(b.id)
FROM categories a
LEFT JOIN categories x ON x.id=a.parent
LEFT JOIN category_x_product b ON b.ctg_id=a.id
group by a.id
Thank you for answers.
Here is some example data:
-- Adminer 4.2.3 MySQL dump
SET NAMES utf8;
SET time_zone = '+00:00';
SET foreign_key_checks = 0;
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
DROP TABLE IF EXISTS `categories`;
CREATE TABLE `categories` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`parent` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `categories` (`id`, `name`, `parent`) VALUES
(1, 'computers', 0),
(2, 'notebooks', 1),
(3, 'lenovo', 2);
DROP TABLE IF EXISTS `products`;
CREATE TABLE `products` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `products` (`id`, `name`) VALUES
(1, 'lenovo thinkpad 001'),
(2, 'lenovo thinkpad 002'),
(3, 'lenovo thinkpad 003'),
(4, 'lenovo thinkpad 004'),
(5, 'lenovo thinkpad 005'),
(6, 'random comp.');
DROP TABLE IF EXISTS `product_x_category`;
CREATE TABLE `product_x_category` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`product_id` int(11) DEFAULT NULL,
`category_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `product_x_category` (`id`, `product_id`, `category_id`) VALUES
(1, 1, 3),
(2, 2, 3),
(3, 3, 3),
(4, 4, 3),
(5, 5, 3),
(6, 6, 1);
-- 2016-02-23 08:16:30
I've tried to run your SQL Query (Create table and insert value).
And I run this query
SELECT a.name, COUNT( b.id )
FROM categories a
LEFT JOIN product_x_category b ON b.category_id = a.id
GROUP BY a.id
And it returns this
This is your product_x_Category table (where category_id --> 3 = lenovo and category_id --> 1 = computer)
I think the result is what you want, isn't it?

mysql trigger - update value, value= row count

I want to run a mysql trigger to update value of table leave_taken col num, when a table called leave was updated, inserted or deleted.
Like if I insert this rows to leave:
INSERT INTO `leave` (`id_leave`, `staff_leave_application_id_staff_leave_application`, `staff_leave_application_staff_id_staff`, `leave_type_id_leave_type`, `date`, `active`, `date_updated`) VALUES
(7, 7, 6, 7, '2013-01-21', 1, '2013-01-18'),
(8, 7, 6, 7, '2013-01-22', 1, '2013-01-18'),
(9, 7, 6, 7, '2013-01-23', 1, '2013-01-18'),
(10, 7, 6, 7, '2013-01-24', 1, '2013-01-18'),
(11, 7, 6, 7, '2013-01-25', 2, '2013-01-18');
then table leave_taken col num value was updated to 5 where:
staff_leave_application_staff_id_staff = currently updated staff_leave_application_staff_id_staff,
and
leave_type_id_leave_type = currently updated leave_type_id_leave_type
I have included the Table below.
Table Leave
CREATE TABLE IF NOT EXISTS `leave` (
`id_leave` int(11) NOT NULL AUTO_INCREMENT,
`staff_leave_application_id_staff_leave_application` int(11) NOT NULL,
`staff_leave_application_staff_id_staff` int(11) NOT NULL,
`leave_type_id_leave_type` int(11) NOT NULL,
`date` date NOT NULL,
`active` int(11) NOT NULL DEFAULT '1',
`date_updated` date NOT NULL,
PRIMARY KEY (`id_leave`,`staff_leave_application_id_staff_leave_application`,`staff_leave_application_staff_id_staff`),
KEY `fk_table1_leave_type1` (`leave_type_id_leave_type`),
KEY `fk_table1_staff_leave_application1` (`staff_leave_application_id_staff_leave_application`,`staff_leave_application_staff_id_staff`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ;
Table Leave taken:
CREATE TABLE IF NOT EXISTS `leave_balance` (
`id_leave_balance` int(11) NOT NULL AUTO_INCREMENT,
`staff_id_staff` int(11) NOT NULL,
`leave_type_id_leave_type` int(11) NOT NULL,
`balance` int(3) NOT NULL,
`date_added` date NOT NULL,
PRIMARY KEY (`id_leave_balance`),
UNIQUE KEY `id_leave_balance_UNIQUE` (`id_leave_balance`),
KEY `fk_leave_balance_staff1` (`staff_id_staff`),
KEY `fk_leave_balance_leave_type1` (`leave_type_id_leave_type`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
First, define a unique key over the identifying columns in your leave table:
ALTER TABLE leave
ADD UNIQUE (staff_leave_application_staff_id_staff, leave_type_id_leave_type);
Then go ahead and define your triggers:
CREATE TRIGGER my_insert_trigger AFTER INSERT ON leave FOR EACH ROW
INSERT INTO leave_taken
(staff_leave_application_staff_id_staff, leave_type_id_leave_type, num)
VALUES
(NEW.staff_leave_application_staff_id_staff, NEW.leave_type_id_leave_type, 1)
ON DUPLICATE KEY UPDATE
num = num + 1;
CREATE TRIGGER my_delete_trigger AFTER DELETE ON leave FOR EACH ROW
UPDATE leave_taken
SET num = num - 1
WHERE staff_leave_application_staff_id_staff = OLD.staff_leave_application_staff_id_staff
AND leave_type_id_leave_type = OLD.leave_type_id_leave_type;
DELIMITER ;;
CREATE TRIGGER my_update_trigger AFTER UPDATE ON leave FOR EACH ROW
IF NOT (
NEW.staff_leave_application_staff_id_staff <=> OLD.staff_leave_application_staff_id_staff
AND NEW.leave_type_id_leave_type <=> OLD.leave_type_id_leave_type
) THEN
UPDATE leave_taken
SET num = num - 1
WHERE staff_leave_application_staff_id_staff = OLD.staff_leave_application_staff_id_staff
AND leave_type_id_leave_type = OLD.leave_type_id_leave_type;
INSERT INTO leave_taken
(staff_leave_application_staff_id_staff, leave_type_id_leave_type, num)
VALUES
(NEW.staff_leave_application_staff_id_staff, NEW.leave_type_id_leave_type, 1)
ON DUPLICATE KEY UPDATE
num = num + 1;
END IF;;
DELIMITER ;