Complex JOIN SQL query in Laravel 5 - mysql

I have three tables that I need to join: products, orders_items, orders
The products table contains, obviously, the products. When a user adds a product to their cart, it creates an order and a line item in the order_items table. When the user pays, it puts the total paid into the orders table. Therefore, purchased products removed from inventory only include products that are attached to an order_item attached to an order that has been marked paid.
I need to return all the products, but also somehow calculate how many are left in inventory. The products table contains a field called "initial_quantity" which is how many of the product we started with. If that field is NULL, there's no limit on the product.
Here is my current query, which works just fine for returning all the products of a certain type:
$swims = Product::where('product_type_id', 1)
->whereDate('visible_date', '<=', Carbon::now())
->where('active', true)
->where(function ($query) {
$query->where('end_date', '>=', Carbon::now())
->orWhere('end_date', null);
})
->get();
Here is the SQL for that query:
select * from `products` where `product_type_id` = 1 and date(`visible_date`) <= '2019-08-08 17:10:12' and `active` = 1 and (`end_date` >= '2019-08-08 17:10:12' or `end_date` is null)
The above query returns three results:
+----+-------------+------------+------------+--------------+------------------+-----------------+--------+
| id | name | base_price | end_date | visible_date | initial_quantity | product_type_id | active |
+----+-------------+------------+------------+--------------+------------------+-----------------+--------+
| 1 | membership | 30.97 | NULL | 2019-08-04 | NULL | 1 | 1 |
| 12 | repellendus | 779.24 | 2027-03-16 | 1990-12-19 | NULL | 1 | 1 |
| 16 | ducimus | 708.33 | NULL | 1999-03-24 | NULL | 1 | 1 |
+----+-------------+------------+------------+--------------+------------------+-----------------+--------+
I can run another query to see how much of each product has been sold:
select product_id, SUM(quantity) sold from `order_items` inner join `orders` on `order_items`.`order_id` = `orders`.`id` and `orders`.`paid` is not null group by `product_id`
This query returns:
+------------+------+
| product_id | sold |
+------------+------+
| 1 | 5 |
| 7 | 3 |
| 11 | 1 |
| 12 | 1 |
+------------+------+
What I'm looking for is a way to combine those two (or similar) queries so I get all the products I'm looking for, plus the quantity of those products that have been sold, to give me a result similar to this:
+----+-------------+------------+------------+--------------+------------------+-----------------+--------+------+
| id | name | base_price | end_date | visible_date | initial_quantity | product_type_id | active | sold |
+----+-------------+------------+------------+--------------+------------------+-----------------+--------+------+
| 1 | membership | 30.97 | NULL | 2019-08-04 | NULL | 1 | 1 | 5 |
| 12 | repellendus | 779.24 | 2027-03-16 | 1990-12-19 | NULL | 1 | 1 | 1 |
| 16 | ducimus | 708.33 | NULL | 1999-03-24 | NULL | 1 | 1 | 0 |
+----+-------------+------------+------------+--------------+------------------+-----------------+--------+------+
I would like a query that returns all products I'm searching for and also how many are remaining. I've tried join, leftJoin, rightJoin, subquery joins and unions. Laravel doesn't seem to have outer joins or I would have tried those too.
I have tried this query and many other iterations and I always get a syntax error:
select * from (`products` where `product_type_id` = 1 and date(`visible_date`) <= '2019-08-08 17:10:12' and `active` = 1 and (`end_date` >= '2019-08-08 17:10:12' or `end_date` is null)) x INNER JOIN (select product_id, SUM(quantity) sold from `order_items` inner join `orders` on `order_items`.`order_id` = `orders`.`id` and `orders`.`paid` is not null group by `product_id`) y ON x.id = y.product_id
Can anybody come up with the query I'm looking for? If not in Laravel then in raw SQL would be fine and I can use it as-is or try to Laravelize it.
Thank you in advance.
Here is my MRE:
CREATE TABLE `products` (
`id` bigint(20) UNSIGNED NOT NULL,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`base_price` double(5,2) NOT NULL,
`end_date` date DEFAULT NULL,
`visible_date` date DEFAULT NULL,
`initial_quantity` smallint(5) UNSIGNED DEFAULT NULL,
`product_type_id` int(10) UNSIGNED NOT NULL,
`active` tinyint(3) UNSIGNED NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `products` (`id`, `name`, `base_price`, `end_date`, `visible_date`, `initial_quantity`, `product_type_id`, `active`) VALUES
(1, 'membership', 30.97, NULL, '2019-08-04', NULL, 1, 1),
(2, 'delectus', 347.44, NULL, '1975-06-08', 45, 1, 0),
(3, 'aut', 283.36, '1981-05-30', '1973-08-18', NULL, 3, 0),
(4, 'adipisci', 984.00, '1986-01-04', '1989-03-29', NULL, 3, 0),
(5, 'voluptas', 310.55, '2012-05-04', '1992-11-16', 45, 2, 1),
(6, 'quia', 657.81, '1976-11-23', '1978-10-23', 57, 2, 0),
(7, 'delectus', 601.91, NULL, '1987-03-09', 53, 2, 1),
(8, 'consequatur', 723.25, '1994-09-24', '1985-01-23', 33, 1, 0),
(9, 'perferendis', 427.33, NULL, '1995-12-08', 51, 3, 1),
(10, 'id', 674.39, '1974-12-13', '2007-05-12', 41, 2, 0),
(11, 'maxime', 133.49, NULL, '1986-07-15', NULL, 2, 1),
(12, 'repellendus', 779.24, '2027-03-16', '1990-12-19', NULL, 1, 1),
(13, 'sit', 956.76, NULL, '1993-07-02', 39, 2, 0),
(14, 'molestiae', 425.16, NULL, '1981-03-25', NULL, 3, 1),
(15, 'omnis', 418.78, '1976-11-03', '2007-10-07', NULL, 3, 1),
(16, 'ducimus', 708.33, NULL, '1999-03-24', NULL, 1, 1),
(17, 'numquam', 328.26, '2011-09-19', '2001-10-07', NULL, 3, 1),
(18, 'est', 962.26, NULL, '1970-12-24', NULL, 1, 0),
(19, 'quis', 520.18, NULL, '1978-03-25', NULL, 3, 0),
(20, 'facere', 891.89, NULL, '1979-10-31', 36, 3, 0),
(21, 'voluptatem', 518.47, '1982-06-26', '1975-03-14', NULL, 1, 1);
COMMIT;
CREATE TABLE `order_items` (
`order_id` bigint(20) UNSIGNED NOT NULL,
`product_id` bigint(20) UNSIGNED NOT NULL,
`quantity` tinyint(3) UNSIGNED NOT NULL DEFAULT '1',
`price` double(5,2) NOT NULL,
`tax` double(5,2) NOT NULL,
`buy_now` tinyint(3) UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `order_items` (`order_id`, `product_id`, `quantity`, `price`, `tax`, `buy_now`, `created_at`, `updated_at`) VALUES
(1, 1, 1, 30.97, 4.03, 1, '2019-08-04 11:35:26', '2019-08-04 11:35:26'),
(1, 12, 1, 779.24, 654.56, 1, '2019-08-04 11:35:26', '2019-08-04 11:35:26'),
(2, 1, 1, 30.97, 4.03, 1, '2019-08-04 11:56:16', '2019-08-04 11:56:16'),
(3, 1, 1, 30.97, 4.03, 1, '2019-08-07 17:25:43', '2019-08-07 17:25:43'),
(3, 7, 1, 601.91, 210.67, 1, '2019-08-07 17:25:43', '2019-08-07 17:25:43'),
(4, 1, 1, 30.97, 4.03, 1, '2019-08-08 15:44:45', '2019-08-08 15:44:45'),
(4, 7, 1, 601.91, 210.67, 1, '2019-08-08 15:44:45', '2019-08-08 15:44:45'),
(5, 1, 1, 30.97, 4.03, 1, '2019-08-08 15:46:07', '2019-08-08 15:46:07'),
(5, 11, 1, 133.49, 88.10, 1, '2019-08-08 15:46:07', '2019-08-08 15:46:07'),
(6, 1, 1, 30.97, 4.03, 1, '2019-08-08 15:46:55', '2019-08-08 15:46:55'),
(6, 16, 1, 708.33, 687.08, 1, '2019-08-08 15:46:55', '2019-08-08 15:46:55'),
(7, 1, 1, 30.97, 4.03, 1, '2019-08-08 15:47:37', '2019-08-08 15:47:37'),
(7, 7, 1, 601.91, 210.67, 1, '2019-08-08 15:47:37', '2019-08-08 15:47:37'),
(8, 1, 1, 30.97, 4.03, 1, '2019-08-08 15:48:13', '2019-08-08 15:48:13'),
(8, 11, 1, 133.49, 88.10, 1, '2019-08-08 15:48:13', '2019-08-08 15:48:13');
CREATE TABLE `orders` (
`id` bigint(20) UNSIGNED NOT NULL,
`user_id` bigint(20) UNSIGNED NOT NULL,
`subtotal` double(7,2) DEFAULT NULL,
`tax` double(7,2) DEFAULT NULL,
`paid` double(7,2) DEFAULT NULL,
`transaction` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `orders` (`id`, `user_id`, `subtotal`, `tax`, `paid`, `transaction`, `created_at`, `updated_at`) VALUES
(1, 1, 810.21, 658.59, 12343.00, NULL, '2019-08-04 11:35:26', '2019-08-04 11:35:26'),
(2, 1, 30.97, 4.03, NULL, NULL, '2019-08-04 11:56:16', '2019-08-04 11:56:16'),
(3, 1, 632.88, 214.70, 847.58, NULL, '2019-08-05 17:25:43', '2019-08-07 17:25:43'),
(4, 5, 632.88, 214.70, 847.58, NULL, '2019-08-08 15:44:45', '2019-08-08 15:44:45'),
(5, 5, 164.46, 92.13, 256.59, NULL, '2019-08-08 15:46:07', '2019-08-08 15:46:07'),
(6, 5, 739.30, 691.11, NULL, NULL, '2019-08-08 15:46:55', '2019-08-08 15:46:55'),
(7, 10, 632.88, 214.70, 847.58, NULL, '2019-08-08 15:47:37', '2019-08-08 15:47:37'),
(8, 10, 164.46, 92.13, NULL, NULL, '2019-08-08 15:48:13', '2019-08-08 15:48:13');

SELECT a.*
, COALESCE(b.sold,0) sold
FROM
( SELECT *
FROM products p
WHERE p.product_type_id = 1
AND DATE(p.visible_date) <= '2019-08-08 17:10:12'
AND p.active = 1
AND (p.end_date >= '2019-08-08 17:10:12' or p.end_date IS NULL)
) a
LEFT
JOIN
( SELECT product_id
, SUM(quantity) sold
FROM order_items oi
JOIN orders o
ON o.id = oi.order_id
AND o.paid is not null
GROUP
BY product_id
) b
ON b.product_id = a.id;
...or, better...
SELECT p.*
, COALESCE(y.sold,0) sold
FROM products p
LEFT
JOIN
( SELECT product_id
, SUM(quantity) sold
FROM order_items oi
JOIN orders o
ON o.id = oi.order_id
AND o.paid is not null
GROUP
BY product_id
) y
ON y.product_id = p.id
WHERE p.product_type_id = 1
AND DATE(p.visible_date) <= '2019-08-08 17:10:12'
AND p.active = 1
AND (p.end_date >= '2019-08-08 17:10:12' OR p.end_date IS NULL)

Related

Nested mysql query over 3 tables does not show the correct result

I have a problem with a nested query.
There are 3 tables
gutschriften_products, orders_products , products
Query
CREATE TABLE IF NOT EXISTS `gutschriften_products` (
`gut_orders_products_id` int(11) NOT NULL AUTO_INCREMENT,
`gut_id` int(11) NOT NULL DEFAULT '0',
`orders_products_id` int(11) NOT NULL DEFAULT '0',
`orders_id` int(11) NOT NULL DEFAULT '0',
`products_id` int(11) NOT NULL DEFAULT '0',
`products_name` varchar(64) DEFAULT NULL,
`products_price` decimal(15,4) NOT NULL DEFAULT '0.0000',
`final_price` decimal(15,4) NOT NULL DEFAULT '0.0000',
`products_quantity` int(2) NOT NULL DEFAULT '0',
PRIMARY KEY (`gut_orders_products_id`)
) ;
INSERT INTO `gutschriften_products` (`gut_orders_products_id`, `gut_id`, `orders_products_id`, `orders_id`, `products_id`, `products_name`, `products_price`, `final_price`, `products_quantity`) VALUES
(1, 1, 12, 108, 375, 'Prod 375', '92.3529', '92.3529', 1),
(2, 2, 13, 109, 375, 'Prod 375', '65.9664', '65.9664', 1),
(3, 3, 51, 110, 377, 'Prod 377', '71.8487', '71.8487', 1),
(4, 4, 40, 111, 432, 'Prod 432', '82.7731', '82.7731', 1),
(5, 4, 41, 112, 427, 'Prod 427', '72.6891', '72.6891', 1),
(6, 4, 42, 113, 420, 'Prod 420', '72.6891', '72.6891', 1),
(7, 4, 43, 114, 423, 'Prod 423', '82.7731', '82.7731', 1),
(8, 4, 44, 115, 423, 'Prod 423', '82.7731', '82.7731', 1),
(9, 5, 59, 116, 451, 'Prod 451', '78.5714', '78.5714', 1);
====
CREATE TABLE IF NOT EXISTS `orders_products` (
`orders_products_id` int(11) NOT NULL AUTO_INCREMENT,
`orders_id` int(11) NOT NULL DEFAULT '0',
`products_id` int(11) NOT NULL DEFAULT '0',
`products_name` varchar(64) DEFAULT NULL,
`products_price` decimal(15,4) NOT NULL DEFAULT '0.0000',
`final_price` decimal(15,4) NOT NULL DEFAULT '0.0000',
`products_quantity` int(2) NOT NULL DEFAULT '0',
PRIMARY KEY (`orders_products_id`),
KEY `orders_id` (`orders_id`),
KEY `orders_id_2` (`orders_id`),
KEY `products_id` (`products_id`)
);
INSERT INTO `orders_products` (`orders_products_id`, `orders_id`, `products_id`, `products_name`, `products_price`, `final_price`, `products_quantity`) VALUES
(12, 108, 375, 'Prod 375', '100.7563', '100.7563', 1),
(13, 109, 375, 'Prod 375', '78.5714', '78.5714', 1),
(14, 110, 376, 'Prod 376', '70.1681', '70.1681', 1),
(15, 111, 377, 'Prod 377', '63.0252', '63.0252', 1),
(16, 112, 376, 'Prod 376', '70.1681', '70.1681', 1),
(17, 113, 377, 'Prod 377', '92.3529', '92.3529', 1),
(18, 114, 375, 'Prod 375', '69.3277', '69.3277', 1),
(19, 115, 376, 'Prod 376', '117.5600', '117.5600', 1),
(20, 116, 377, 'Prod 377', '79.8319', '79.8319', 1);
====
CREATE TABLE IF NOT EXISTS `products` (
`products_id` int(11) NOT NULL AUTO_INCREMENT,
`products_quantity` int(4) NOT NULL DEFAULT '0',
`products_price` decimal(15,8) NOT NULL DEFAULT '0.00000000',
`products_date_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`products_status` tinyint(1) NOT NULL DEFAULT '0',
`manufacturers_id` int(11) DEFAULT NULL,
`products_ordered` int(11) NOT NULL DEFAULT '0',
`products_ek` double(15,8) NOT NULL DEFAULT '0.00000000',
`products_verfuegbar` int(2) NOT NULL DEFAULT '1',
`products_geprueft` datetime NOT NULL,
`products_lagernd` int(4) NOT NULL,
PRIMARY KEY (`products_id`),
KEY `idx_products_date_added` (`products_date_added`)
) ;
INSERT INTO `products` (`products_id`, `products_quantity`, `products_price`, `products_date_added`, `products_status`, `manufacturers_id`, `products_ordered`, `products_ek`, `products_verfuegbar`, `products_geprueft`, `products_lagernd`) VALUES
(375, 18, '71.00840336', '2015-05-04 17:44:45', 1, 16, 75, 41.00000000, 1, '0000-00-00 00:00:00', 0),
(376, 10, '77.73109244', '2015-05-05 10:28:31', 1, 16, 67, 45.00000000, 1, '0000-00-00 00:00:00', 0),
(377, 10, '71.00840336', '2015-05-05 10:45:08', 1, 16, 52, 41.00000000, 1, '0000-00-00 00:00:00', 0),
(378, 8, '71.00840336', '2015-05-05 10:52:20', 1, 16, 35, 41.00000000, 1, '0000-00-00 00:00:00', 0),
(379, 10, '77.73109244', '2015-05-05 10:56:47', 1, 16, 36, 45.00000000, 1, '0000-00-00 00:00:00', 0);
I want to find out which items are sold / returned how often. Unfortunately, my approach only prints those items that have been sold AND returned. Items that have NEVER been sold or returned will not be displayed.
SELECT
(verkauft - gutschrift)*(P.products_price - products_ek) / (DATEDIFF(CURDATE(), P.products_date_added))*365 AS GEZE,
DATEDIFF(CURDATE(), P.products_date_added) AS dtage,
products_quantity,
DATE_FORMAT(P.products_date_added, " % d. % m. % Y") AS hinzu,
P.products_date_added,
A.products_id,
A.products_name,
verkauft,
gutschrift,
final_price,
verkauft - gutschrift AS summe,
gutschrift / verkauft*100 AS rquote,
products_ek AS EK,
P.products_price AS VK,
P.products_date_added AS aufgenommen,
P.manufacturers_id,
(
verkauft - gutschrift
)
*(P.products_price - products_ek) AS gewinn,
products_lagernd
FROM
(
select
products_id,
products_name,
sum(products_quantity) as verkauft
from
orders_products
where
orders_id BETWEEN 1 AND 11847
group by
products_id
)
AS A
JOIN
(
select
final_price,
products_id,
products_name,
sum(products_quantity) as gutschrift
from
gutschriften_products
where
final_price > 0
AND orders_id BETWEEN 1 AND 11847
group by
products_id
)
AS B
ON A.products_id = B.products_id
JOIN
(
select
products_geprueft,
products_id,
products_status,
manufacturers_id,
products_quantity,
products_ek,
products_price,
products_lagernd,
products_date_added
from
products
)
AS P
ON P.products_id = B.products_id
where
products_status > 0
AND 1 = 1
order by
products_name ASC,
products_id
Result:
There are only two rows with product_id = 375 and 377
But I have 3 other products 376, 378, 379
Why aren't they listed?
I know I shouldn't do this but I'm a bit board so.... (please compare it to your original sql and reach conclusions)
SELECT
(verkauft - gutschrift)*(P.products_price - products_ek) / (DATEDIFF(CURDATE(), P.products_date_added))*365 AS GEZE,
DATEDIFF(CURDATE(), P.products_date_added) AS dtage,
P.products_quantity,
DATE_FORMAT(P.products_date_added, "%d.%m.%Y") AS hinzu,
P.products_date_added,
P.products_id,
A.products_name,
verkauft,
gutschrift,
final_price,
verkauft - gutschrift AS summe,
gutschrift / verkauft*100 AS rquote,
products_ek AS EK,
P.products_price AS VK,
P.products_date_added AS aufgenommen,
P.manufacturers_id,
(verkauft - gutschrift ) *(P.products_price - products_ek) AS gewinn,
products_lagernd
FROM products P
LEFT JOIN ( select
products_id,
products_name,
sum(products_quantity) as verkauft
from orders_products
where orders_id BETWEEN 1 AND 11847
group by products_id ) AS A ON P.products_id = A.products_id
LEFT JOIN (select
final_price,
products_id,
products_name,
sum(products_quantity) as gutschrift
from gutschriften_products
where final_price > 0 AND orders_id BETWEEN 1 AND 11847
group by products_id ) AS B ON A.products_id = B.products_id
where products_status > 0
order by products_name ASC, products_id;
please reply if it's good for you...

how to calculate percentage and generate below result

I have a table schema
CREATE TABLE `charge` (
`charge_id` int(11) NOT NULL AUTO_INCREMENT,
`selling_date` date DEFAULT NULL,
`amount` decimal(10,2) DEFAULT NULL,
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`charge_type_id` int(11) DEFAULT NULL,
PRIMARY KEY (`charge_id`)
);
CREATE TABLE `charge_type` (
`charge_type_id` int(11) NOT NULL AUTO_INCREMENT,
`charge_type` varchar(20) NOT NULL,
`is_deleted` tinyint(1) DEFAULT '0',
PRIMARY KEY (`charge_type_id`)
);
CREATE TABLE `charge_type_tax_list` (
`tax_type_id` int(11) NOT NULL,
`charge_type_id` int(11) NOT NULL,
PRIMARY KEY (`tax_type_id`,`charge_type_id`)
);
CREATE TABLE `tax_type` (
`tax_type_id` int(11) NOT NULL AUTO_INCREMENT,
`tax_type` varchar(35) NOT NULL,
`percentage` decimal(5,4) NOT NULL DEFAULT '0.0000',
`is_deleted` tinyint(1) DEFAULT '0',
PRIMARY KEY (`tax_type_id`)
);
INSERT INTO charge (
`selling_date`,
`amount`,
`is_deleted`,
`charge_type_id`
)
VALUES
("2013-12-01", 50, 0, 1),
("2013-12-01", 20, 0, 2),
("2013-12-02", 40, 0, 1),
("2013-12-02", 30, 0, 3),
("2013-12-02", 30, 1, 1),
("2013-12-03", 10, 0, 1);
INSERT INTO charge_type (
`charge_type_id`,
`charge_type`,
`is_deleted`
)
VALUES
(1, "room charge", 0),
(2, "snack charge", 0),
(3, "deleted charge", 1);
INSERT INTO charge_type_tax_list (
`tax_type_id`,
`charge_type_id`
)
VALUES
(1, 1),
(2, 1),
(3, 1),
(1, 2),
(1, 3);
INSERT INTO tax_type (
`tax_type_id`,
`tax_type` ,
`percentage`,
`is_deleted`
)
VALUES
(1, "GST", 0.05, 0),
(2, "HRT", 0.04, 0),
(3, "DELETED TAX", 0.10, 1);
I want you to produce a query that lists all charges and tax-calculated totals
With the given schema, your query should produce:
Selling Date Charge Type Amount Tax
2013-12-01 Room Charge 50.00 4.50
2013-12-01 Snack Charge 20.00 1.00
2013-12-02 Room Charge 40.00 3.60
2013-12-03 Room Charge 10.00 0.90
Do not display charges that are deleted (is_deleted is flagged)
Do not display charges that have charge_types that are deleted (is_deleted is flagged)
Do not consider tax_type that is deleted (is_deleted), but the containing charge_type should still be displayed)
Please help me I need it urgently.Thanks
Please read on MySQL Join Made Easy to understand how joins are used. Here is a query that should give the result you want by joining the tables on the common attributes.
SELECT A.`selling_date` AS `Selling Date`, B.`charge_type` AS `Charge Type`
, A.`amount` AS `Amount`, (A.`amount` * D.`percentage`) AS `Tax` FROM
`charge` A LEFT JOIN
`charge_type` B ON A.`charge_type_id`=B.`charge_type_id` INNER JOIN
`charge_type_tax_list` C ON B.`charge_type_id`=C.`charge_type_id`
INNER JOIN `tax_type` D ON C.`tax_type_id`=D.`tax_type_id`
WHERE
A.`is_deleted`=0 AND B.`is_deleted`=0 AND
D.`is_deleted`=0;
Here is an SQL FIDDLE DEMO
This query below will get the result that you want
select charge.selling_date as SellingDate,
charge.amount as Amount,
charge_type.charge_type as ChargeType,
sum(charge.amount * tax_type.percentage) as Tax
From charge
inner join charge_type on charge.charge_type_id=charge_type.charge_type_id,
tax_type
where charge.is_deleted=0 and charge_type.is_deleted=0 and tax_type.is_deleted=0
group by charge.selling_date, charge.amount,charge_type.charge_type

Mysql : Pivot table According to status

My DB structure and details below
CREATE TABLE `tbldakmst` (
`inwardId` int(11) NOT NULL,
`dakType` int(3) DEFAULT NULL,
`dakMarkTo` int(4) DEFAULT NULL,
`letterNo` varchar(100) DEFAULT NULL,
`markDeptt` varchar(20) DEFAULT NULL,
`dakSenderName` varchar(256) DEFAULT NULL,
`subject` varchar(256) DEFAULT NULL,
`remarks` text,
`comments` text,
`handoverDate` datetime DEFAULT NULL,
`handoverTo` int(11) DEFAULT NULL,
`forwardedTo` int(11) DEFAULT NULL,
`forwardedOn` datetime DEFAULT NULL,
`forwardedFrom` int(11) DEFAULT NULL,
`status` enum('0','1','2','3','4','5') DEFAULT NULL COMMENT '0=>CREATED, 1=>MARK TO, 2 => FORWARD TO, 3=>INITIATED, 4=>INITIATED AND DISPOSED, 5=>DISPOSED',
`createdBy` int(11) DEFAULT NULL,
`createdOn` datetime DEFAULT CURRENT_TIMESTAMP,
`modifiedBy` int(11) DEFAULT NULL,
`modifiedOn` datetime DEFAULT NULL,
`fileInitiateBy` int(11) DEFAULT NULL,
`fileInitiatedOn` datetime DEFAULT NULL,
`disposedBy` int(11) DEFAULT NULL,
`disposedOn` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `tbldakmst` (`inwardId`, `dakType`, `dakMarkTo`, `letterNo`, `markDeptt`, `dakSenderName`, `subject`, `remarks`, `comments`, `handoverDate`, `handoverTo`, `forwardedTo`, `forwardedOn`, `forwardedFrom`, `status`, `createdBy`, `createdOn`, `modifiedBy`, `modifiedOn`, `fileInitiateBy`, `fileInitiatedOn`, `disposedBy`, `disposedOn`) VALUES
(1, 0, 3, 'letter 5634', 'Office Dak', 'dheeraj kumar nayak', 'My subject data is here', 'Remrks Datammm VBCBCBBBBB', 'disposed again', '1970-01-26 00:00:00', 3, 3, '2017-05-02 15:14:50', 2, '5', 2, '2017-05-01 17:40:32', 3, '2017-05-07 15:42:40', 3, '2017-05-07 14:07:35', 3, '2017-05-07 14:39:51'),
(2, 0, 4, 'letter no 787887', 'Office Dak', 'kAMLESH kUMAR', 'subj', 'Remarks data', 'MY COMMENTS', '2017-05-02 15:14:50', 4, 2, '2017-05-02 15:14:50', 2, '2', 0, '2017-05-02 11:13:00', 2, '2017-05-05 13:00:44', NULL, NULL, 2, NULL),
(3, 0, 2, 'letter 5634', 'Office Dak', 'dheeraj kumar nayak', 'Need operator credentiasl', 'file putted edited', 'gdfgfg', '1970-01-01 00:00:00', 2, 3, NULL, 2, '1', 2, '2017-05-03 11:03:49', 2, '2017-05-04 14:48:48', NULL, NULL, NULL, NULL),
(4, 0, 2, 'letter 567', 'Office Dak', 'Dheraj Kumar', 'operator activation request from CSC-SPV', 'Personal Visit by EA', 'Disposed Now', '2017-05-07 00:00:00', 2, 2, NULL, 3, '5', 3, '2017-05-07 15:46:06', 2, '2017-05-07 16:10:14', 2, '2017-05-07 16:09:17', 2, '2017-05-07 16:10:14'),
(5, 0, 3, 'letter no 5566rr', 'Office Dak', 'ranjeet vaghle', 'operator request', 'proceed', 'File issues resolved and file is diposed', '0000-00-00 00:00:00', 3, 2, NULL, 3, '4', 3, '2017-05-07 15:55:32', 2, '2017-05-07 16:06:58', 2, '2017-05-07 16:06:58', 2, '2017-05-07 16:06:58'),
(6, 0, 2, 'letter 5634', 'Office Dak', 'dheeraj kumar nayak', 'hjjh', 'hjkhj', NULL, '0000-00-00 00:00:00', 2, NULL, NULL, NULL, '1', 2, '2017-05-07 17:27:36', NULL, NULL, NULL, NULL, NULL, NULL),
(7, 0, 2, 'Letter Number -56788899', 'Office Dak', 'dheeraj kumar nayak', 'dsfs', 'fdsfdsf', 'initiated', '0000-00-00 00:00:00', 2, 2, NULL, 2, '3', 2, '2017-05-07 17:51:56', 2, '2017-05-07 17:52:54', 2, '2017-05-07 17:52:54', NULL, NULL);
ALTER TABLE `tbldakmst`
ADD PRIMARY KEY (`inwardId`);
ALTER TABLE `tbldakmst` MODIFY `inwardId` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
I have tried:
SELECT
sum(CASE
WHEN status = '1' THEN 1
ELSE 0
END) AS 'pending',
sum(CASE
WHEN status = '3' THEN 1
ELSE 0
END) AS 'initiated',
sum(CASE
WHEN status = '4' OR status = '5' THEN 1
ELSE 0
END) AS 'disposed' FROM tbldakmst
Above Query Output Was :
pending initiated disposed
2 1 3
<!-- Note:Status(0,1) ==>Pending ,Status (3) ==>Initiated,Status(4,5)==>Disposed
column FileInitiatedBy => User Value which one has initiated file.
Column disposedBy=> User Value which one has disposed file.
Column dakmarkTo => User Value which one have pending file -->
But I want Result Like this
User | Pending | Initiated | Disposed |
------------------------------------------------------
User 2 | 1 | 1 | 2 |
------------------------------------------------------
User 3 | 2 | 3 | 4 |
------------------------------------------------------
SELECT u.name AS 'Name',
sum(CASE
WHEN tb.status in ('0','1') AND (u.id = tb.dakMarkTo OR u.id = tb.createdBy) THEN 1
ELSE 0
END) AS 'pending' ,
sum(CASE
WHEN tb.status in ('3') AND u.id = tb.fileInitiateBy THEN 1
ELSE 0
END) AS 'initiated',
sum(CASE
WHEN tb.status in ('4', '5') AND u.id = tb.disposedBy THEN 1
ELSE 0
END) AS 'disposed'
FROM
tbldakmst tb, user u
group by u.name

Else is not running in mysql Query

I have below query. In this I have yes and no case.
yes is accessing but else part is not working . Please have a look on this.
SELECT SalesChannel.name , count(Transaction.category_id) as count, (case when (Transaction.no_of_units > 0 and Transaction.mop > 0) THEN 'yes' ELSE 'No' END) AS Is_Present from outlets Outlet inner join transactions Transaction on Outlet.id = Transaction.outlet_id inner join sale_channels SalesChannel on SalesChannel.id = Outlet.sale_channel_id group by SalesChannel.name
the output should be as below
KU Electrical
Yes 6 2
No 1 2
6 is counter of KU and Yes refers the presence,similarly No is non presence of KU
select SalesChannel.name ,
Transaction.category_id,
count(Transaction.category_id) as count,
from outlets Outlet inner join transactions Transaction on Outlet.id = Transaction.outlet_id inner join sale_channels SalesChannel on SalesChannel.id = Outlet.sale_channel_id group by SalesChannel.name
below are three tables which i used
1. transactions
CREATE TABLE IF NOT EXISTS `transactions` (
`id` int(11) NOT NULL,
`zone_id` int(11) NOT NULL,
`state_id` int(11) NOT NULL,
`city_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
`sub_category_id` int(11) NOT NULL,
`brand_id` int(11) NOT NULL,
`model_id` int(11) NOT NULL,
`outlet_id` int(11) NOT NULL,
`no_of_units` int(11) NOT NULL,
`mop` decimal(10,2) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `transactions`
--
INSERT INTO `transactions` (`id`, `zone_id`, `state_id`, `city_id`, `category_id`, `sub_category_id`, `brand_id`, `model_id`, `outlet_id`, `no_of_units`, `mop`) VALUES
(1, 2, 2, 2, 2, 1, 1, 1, 1, 3, '6.00'),
(2, 2, 2, 2, 2, 1, 1, 1, 1, 3, '6.00'),
(3, 1, 1, 1, 1, 1, 1, 1, 1, 4, '2.00'),
(4, 2, 2, 2, 1, 1, 1, 1, 2, 4, '2.00');
2.outlets
CREATE TABLE IF NOT EXISTS `outlets` (
`id` int(11) NOT NULL,
`outlet_code` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`zone_id` int(11) NOT NULL,
`state_id` int(11) NOT NULL,
`city_id` int(11) NOT NULL,
`sale_channel_id` int(11) NOT NULL,
`is_active` tinyint(1) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `outlets`
--
INSERT INTO `outlets` (`id`, `outlet_code`, `name`, `zone_id`, `state_id`, `city_id`, `sale_channel_id`, `is_active`, `created`, `modified`) VALUES
(1, '1508', 'Ashok electricals', 2, 2, 2, 1, 1, '2016-10-03 00:00:00', '2016-10-03 00:00:00'),
(2, '1233', 'vinayak electricals', 1, 1, 1, 2, 1, '2016-10-04 00:00:00', '2016-10-04 00:00:00');
3. sale_chennals
CREATE TABLE IF NOT EXISTS `sale_channels` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`is_active` tinyint(1) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `sale_channels`
--
INSERT INTO `sale_channels` (`id`, `name`, `is_active`, `created`, `modified`) VALUES
(1, 'KU', 1, '2016-10-03 00:00:00', '2016-10-03 00:00:00'),
(2, 'Electricals', 1, '2016-10-04 00:00:00', '2016-10-04 00:00:00');
There is no data in tables that match for the else condition. Your condition is that "Transaction.no_of_units >0 AND Transaction.mop >0" that is not match in table value of both fields are greater than 0.
Otherwise, else condition works fine.
You are aggregating your data so as to get one row per SalesChannel.name. There may be some transaction records that result in 'Yes' and others in 'No' for a SalesChannel.name, so what then is Is_Present supposed to be?
Another issue with your query is that the sale channels are in a table. There are currently two of them, but there could be three or four or thousands sometime. A SQL query doesn't produce a result with a variable number of columns. The columns must be known beforehand. So a possible result could look like this:
Name Yes No
KU 6 1
Electrical 2 2
because you know you want it to be Yes or No only, no matter how many channels.
The query:
select
sc.name,
count(case when t.no_of_units > 0 and t.mop > 0 then 1 end) as yes,
count(case when t.no_of_units <= 0 or t.mop <= 0 then 1 end) as no
from sale_channels sc
join outlet o on o.sale_channel_id = sc.id
join transactions t on t.outlet_id = o.id;

MySQL - Selecting rows who's id is not present as a foreign key in another table

In my rails app I have two tables - device_ports and circuits. My goal is to get a list of device_ports whose id is not being used in the physical_port_id column of the circuits table.
I have done something similar before on other tables but here my query only returns one row when it should return 23 rows - there are 24 device ports for this device and one is in use.
select id, name, device_id, multiuse
from device_ports
where (device_id = 6 and multiuse = 1)
or device_ports.id not in (select physical_port_id from circuits)
So this query gets all multiuse ports (so even if the id was referenced in the foreign key, this row should still be returned) and should also get all rows where the device_id is 6 but is not referenced in circuits but only the multiuse row is being returned.
The result from the query is
id | name | device_id | multiuse
------------------------------------
268 | test-1 | 6 | 1
I did try to create an sql fiddle but the build just seems to timeout.
CREATE TABLE `device_ports` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`device_id` int(11) DEFAULT NULL,
`name` tinytext,
`speed` tinytext,
`multiuse` tinyint(1) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=291 DEFAULT CHARSET=latin1;
INSERT INTO `device_ports` (`id`, `device_id`, `name`, `speed`, `multiuse`, `created_at`, `updated_at`)
*emphasized text*VALUES
(1, 1, 'Test Device Port', '100', 0, NULL, NULL),
(2, 1, 'Test Port 2', '300', 1, NULL, NULL),
(289, 6, 'test-22', '100', 0, NULL, NULL),
(290, 6, 'test-23', '100', 0, NULL, NULL),
(288, 6, 'test-21', '100', 0, NULL, NULL),
(287, 6, 'test-20', '100', 0, NULL, NULL),
(286, 6, 'test-19', '100', 0, NULL, NULL),
(284, 6, 'test-17', '100', 0, NULL, NULL),
(285, 6, 'test-18', '100', 0, NULL, NULL),
(283, 6, 'test-16', '100', 0, NULL, NULL),
(282, 6, 'test-15', '100', 0, NULL, NULL),
(281, 6, 'test-14', '100', 0, NULL, NULL),
(280, 6, 'test-13', '100', 0, NULL, NULL),
(279, 6, 'test-12', '100', 0, NULL, NULL),
(278, 6, 'test-11', '100', 0, NULL, NULL),
(277, 6, 'test-10', '100', 0, NULL, NULL),
(276, 6, 'test-9', '100', 0, NULL, NULL),
(275, 6, 'test-8', '100', 0, NULL, NULL),
(274, 6, 'test-7', '100', 0, NULL, NULL),
(273, 6, 'test-6', '100', 0, NULL, NULL),
(272, 6, 'test-5', '100', 0, NULL, NULL),
(271, 6, 'test-4', '100', 0, NULL, NULL),
(270, 6, 'test-3', '100', 0, NULL, NULL),
(269, 6, 'test-2', '100', 0, NULL, NULL),
(268, 6, 'test-1', '100', 1, NULL, NULL),
(267, 6, 'test-0', '100', 0, NULL, NULL);
CREATE TABLE `circuits` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`organisation_id` int(11) DEFAULT NULL,
`physical_port_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=248 DEFAULT CHARSET=latin1;
INSERT INTO `circuits` (`id`, `organisation_id`, `physical_port_id`)
VALUES (1, 125, 267);
You could try using a LEFT OUTER JOIN:
SELECT DISTINCT d.id, d.name, d.device_id, d.multiuse
FROM device_ports d
LEFT OUTER JOIN circuits c ON c.physical_port_id = d.id
WHERE
(c.physical_port_id IS NULL AND d.device_id = 6)
OR (d.multiuse = 1 AND d.device_id = 6)
ORDER BY d.id
There are several techniques for this query, take a look at What's the difference between NOT EXISTS vs. NOT IN vs. LEFT JOIN WHERE IS NULL?.
SELECT p.*
FROM device_ports p
LEFT
JOIN circuits c
ON c.physical_port_id = p.id
WHERE p.device_id = 6
AND multiuse = 1
AND c.id IS NULL;