Count element between 3 tables with mySQL - mysql

I've got these 3 tables:
___Kardex
|--------|---------|-------------|
| KDX_Id | KDX_VIP | KDX_Regular |
|--------|---------|-------------|
| 1 | No | No |
| 2 | No | No |
|--------|---------|-------------|
___BillableDatas
|--------|---------------|
| BIL_Id | BIL_BookingId |
|--------|---------------|
| 1 | 99 |
| 2 | 99 |
| 3 | 100 |
|--------|---------------|
___Bookings
|--------|--------------|
| BOO_Id | BOO_ClientId |
|--------|--------------|
| 99 | 1 |
| 100 | 2 |
|--------|--------------|
I want to loop into ___Kardex and count for each client:
- The number of bookings the client booked (containing in ___Bookings).
- The number of nights the client spent (containing in ___BillableDatas).
So I tried:
SELECT
KDX_Id,
(
SELECT COUNT(BOO_Id)
FROM ___Bookings
WHERE ___Kardex.KDX_Id = ___Bookings.BOO_ClientId
) AS nb_bookings,
(
SELECT COUNT(BIL_Id)
FROM ___BillableDatas
WHERE ___Kardex.KDX_Id = ___Bookings.BOO_ClientId
AND ___Bookings.BOO_Id = ___BillableDatas.BIL_BookingId
) AS nb_bookings
FROM ___Kardex
But I get empty datas.
Could you please help ?
Here the SQLFiddle: http://sqlfiddle.com/#!9/cf1832
The expected result is:
|--------|-------------|-----------|
| KDX_Id | nb_bookings | nb_nights |
|--------|-------------|-----------|
| 1 | 1 | 2 |
| 2 | 1 | 1 |
|--------|-------------|-----------|
Thanks.

Here you go :
SELECT
KDX_Id,
(
SELECT COUNT(BOO_Id)
FROM ___Bookings
WHERE KDX_Id = ___Bookings.BOO_ClientId
) AS nb_bookings,
(
SELECT COUNT(BIL_Id)
FROM ___Bookings, ___BillableDatas
WHERE ___Bookings.BOO_Id = ___BillableDatas.BIL_BookingId
AND KDX_Id = ___Bookings.BOO_ClientId
) AS nb_nights
FROM ___Kardex

Related

MySQL query with sum fields from other table, with a twist

Sorry for the vague title, but I don't know how to word this type of problem better. Here is a simple example to explain it. I have to tables: OrderItemList and OrderHistoryLog.
OrderItemList:
|------------------------------|
| OrderNo | ItemNo | Loc | Qty |
|------------------------------|
| 100 | A | 1 | 1 |
| 101 | A | 1 | 2 |
| 102 | A | 1 | 1 |
| 103 | A | 2 | 1 |
| 104 | A | 2 | 1 |
OrderHistoryLog:
|------------------------------|
| OrderNo | ItemNo | Loc | Qty |
|------------------------------|
| 50 | A | 1 | 5 |
| 51 | A | 1 | 2 |
| 100 | A | 1 | 1 |
| 102 | A | 1 | 3 |
| 103 | A | 2 | 1 |
I need to show the records in the OrderItemList along with a LocHistQty field, which is the sum(Qty) from the OrderHistoryLog table for a given Item and Location, but only for the orders that are present in the OrderItemList.
For the above example, the result should be:
Result:
|------------------------------------------------------
| OrderNo | ItemNo | Loc | Qty | HistQty | LocHistQty |
|------------------------------|-----------------------
| 100 | A | 1 | 1 | 1 | 4 |
| 101 | A | 1 | 2 | 0 | 4 |
| 102 | A | 1 | 1 | 3 | 4 |
| 103 | A | 2 | 1 | 1 | 1 |
| 104 | A | 2 | 1 | 0 | 1 |
It is the last field, LocHistQty that I could use some help with. Here is what I started with (does not work):
select OI.OrderNo, OI.ItemNo, OI.Loc, OI.Qty, IFNULL(OL.Qty, 0) as HistQty, OL2.LocHistQty
from OrderItemList OI
left join OrderItemLog OL on OL.OrderNo = OI.OrderNo and OL.ItemNo = OI.ItemNo
join
(
select ItemNo, Loc, sum(qty) as LocHistQty
from zOrderItemLog
group by ItemNo, Loc
) as OL2
on OL2.ItemNo = OI.ItemNo and OL2.Loc = OI.Loc
order by OrderNo
The issue is with the above SQL is that LocHistQty contains the summary of the Qty for all orders (=11 for Loc 1 and 1 for Loc 2), not only the ones in OrderItemList.
Lastly, the real data is voluminous and query performance is important.
Help would be much appreciated.
The subquery can join with OrderItemList to restrict the order numbers that it sums.
select OI.OrderNo, OI.ItemNo, OI.Loc, OI.Qty, IFNULL(OL.Qty, 0) as HistQty, OL2.LocHistQty
from OrderItemList OI
left join OrderItemLog OL on OL.OrderNo = OI.OrderNo and OL.ItemNo = OI.ItemNo
join
(
select OL.ItemNo, OL.Loc, sum(OL.qty) as LocHistQty
from OrderItemLog AS OL
JOIN OrderItemList AS OI ON OL.OrderNo = OI.OrderNo
group by OL.ItemNo, OL.Loc
) as OL2
on OL2.ItemNo = OI.ItemNo and OL2.Loc = OI.Loc
order by OrderNo
DEMO
Option 1
SELECT
OrderNo,
ItemNo,
Loc,
Qty,
(SELECT
Qty
FROM
OrderHistoryLog AS A
WHERE
A.OrderNo = B.OrderNo AND A.Loc = B.Loc) AS HistQty,
(SELECT
SUM(Qty)
FROM
OrderHistoryLog AS D
WHERE
D.OrderNo = B.OrderNo AND D.Loc = B.Loc) AS LocHistQty
FROM
OrderItemList AS B;
Option 2
SELECT
B.OrderNo,
B.ItemNo,
B.Loc,
B.Qty,
C.Qty AS HistQty,
(SELECT
SUM(Qty)
FROM
OrderHistoryLog AS A
WHERE
A.OrderNo = B.OrderNo AND A.Loc = B.Loc) AS LocHistQty
FROM
OrderItemList AS B,
OrderHistoryLog AS C
WHERE
C.OrderNo = B.OrderNo AND C.Loc = B.Loc;

Selecting multiple MIN columns and other data from same table

Evening. Hope someone can help. Been stumped with this for a few days now...
I have the following table....
| ID | Supplier | Item_1 | Cost_1 | Item_2 | Cost_2 | Item_3 | Cost_3 |
+----+----------+--------+--------+--------+--------+--------+--------+
| 1 | 1 | 732w | 3.99 | 314d | 7.58 | 399p | 15.44 |
| 1 | 2 | SyYh33 | 3.78 | GjuUh4 | 7.60 | 2su7js | 15.45 |
| 1 | 3 | 5443 | 4.01 | 9833 | 7.63 | 7433 | 15.22 |
| 2 | 1 | 596q | 15.42 | 933k | 28.56 | 732c | 69.99 |
| 2 | 2 | hyjs9k | 15.86 | ka7snf | 28.99 | h23nfs | 68.99 |
| 2 | 3 | 5477 | 14.99 | 5658 | 28.49 | 8153 | 70.15 |
+----+----------+--------+--------+--------+--------+--------+--------+
Now what i would like to do is return the cheapest price from columns Cost_1, Cost_2, Cost_3 with it's corresponding Item column and Supplier for each ID....
So basically would like the following result
| ID | Supplier_1 | Item_1 | Cost_1 | Supplier_2 | Item_2 | Cost_2 | Supplier_3 | Item_3 | Cost_3 |
+----+------------+--------+--------+------------+--------+--------+------------+--------+--------+
| 1 | 2 | SyYh33 | 3.78 | 1 | 314d | 7.58 | 3 | 7433 | 15.22 |
| 2 | 3 | 5477 | 14.99 | 3 | 5658 | 28.49 | 2 | h23nfs | 68.99 |
Any pointers would be great. Tried with joins and MIN() but i haven't been able to return the desired results. Hopefully there is a MySQL guru out there that can put me out of my misery. Thanks in advance
Normalize your schema - Otherwise you will have to live with queries like this:
select f.ID,
i1.Supplier as Supplier_1,
i1.Item_1,
i1.Cost_1,
i2.Supplier as Supplier_2,
i2.Item_2,
i2.Cost_2,
i3.Supplier as Supplier_3,
i3.Item_3,
i3.Cost_3
from (select distinct ID from following_table) f
join following_table i1 on i1.ID = f.ID and i1.Supplier = (
select t.Supplier
from following_table t
where t.ID = i1.ID
order by Cost_1 asc
limit 1
)
join following_table i2 on i2.ID = f.ID and i2.Supplier = (
select t.Supplier
from following_table t
where t.ID = i2.ID
order by Cost_2 asc
limit 1
)
join following_table i3 on i3.ID = f.ID and i3.Supplier = (
select t.Supplier
from following_table t
where t.ID = i3.ID
order by Cost_3 asc
limit 1
)
http://sqlfiddle.com/#!9/04933/2
I think what you are looking for is a UNION to combine your results.
SELECT *
FROM your_table
WHERE Cost_1 = (SELECT MIN(Cost_1) FROM your_table)
UNION
SELECT *
FROM your_table
WHERE Cost_2 = (SELECT MIN(Cost_2) FROM your_table)
UNION
SELECT *
FROM your_table
WHERE Cost_3 = (SELECT MIN(Cost_3) FROM your_table)

Return a ranking from tables with MySQL

Here my table structure:
___Rooms:
|--------|------------|
| ROO_Id | ROO_Name |
|--------|------------|
| 1 | Room 1 |
| 2 | Room 2 |
| 3 | Room 3 |
|--------|------------|
___Bookings:
|--------|------------|
| BOO_Id | BOO_RoomId |
|--------|------------|
| 1 | 1 |
| 2 | 2 |
| 3 | 2 |
|--------|------------|
___BillableDatas:
|--------|---------------|------------|------------|
| BIL_Id | BIL_BookingId | BIL_Date | BIL_Item |
|--------|---------------|------------|------------|
| 1 | 1 | 2017-02-21 | Night |
| 2 | 1 | 2017-02-22 | Night |
| 3 | 1 | 2017-02-23 | Night |
| 4 | 1 | 2017-02-24 | Night |
| 5 | 2 | 2017-02-30 | Night |
| 6 | 2 | 2017-02-31 | Night |
| 7 | 1 | 2017-02-31 | Night |
|--------|---------------|------------|------------|
I would like to know the most popular room.
The desired result should be:
|------------|------------|------------|
| ROO_Name | Night Nb | Percentage |
|------------|------------|------------|
| Room 1 | 5 | 71.42 |
| Room 2 | 2 | 28.57 |
| Room 3 | 0 | 0 |
|------------|------------|------------|
What I already tried:
SELECT r.ROO_Id
, Sum(CASE WHEN BOO_Id IS NULL THEN 0 ELSE 1 END) NumBookings
, Concat(
Format(
Sum(CASE WHEN BOO_Id IS NULL THEN 0 ELSE 1 END)
/ TotalBookings
* 100
, 0) ) AS PercentageTotal
FROM ( ___Rooms r LEFT JOIN ___Bookings b ON r.ROO_Id = b.BOO_RoomId
) INNER JOIN (SELECT BOO_HotelId
, Count(*) AS TotalBookings
FROM ___Bookings
GROUP BY BOO_HotelId
) AS TotalHotelBookings
ON r.ROO_HotelId = TotalHotelBookings.BOO_HotelId
WHERE r.ROO_HotelId = :hotel_id
GROUP BY r.ROO_Id
ORDER BY NumBookings DESC
But it doesn't work actually.
You could use the SQL Fiddle:
http://sqlfiddle.com/#!9/390b1
try this
select Roo_Name,coalesce(bookid,0) as nightdb,coalesce(bookid * 10/Boo_Id,0) as percentage
from ___Rooms r1
left join
(select count(BOO_RoomId) as book, BOO_Id
from ___Bookings group by BOO_Id) b1
on r1.Roo_Id = b1.Boo_id
left join
(select count(Bil_BookingId) as bookid,BIL_BookingId
from ___BillableDatas
group by BIL_BookingId) b2
on b2.BIL_BookingId = b1.BOO_Id group by r1.Roo_Name;
DEMO

Get minimum from result with GROUP BY in MySQL

I have table it store hierarchy data in MySQL this table store stable relation but if each user less than 1000 buy removed and user User a lower level replace this is my code and work fine, after GROUP BY it contain all ancestor of descendant with compare then COUNT(*) AS level count level each user. This I have SQL code to compress data According to minimum buy for each user
+-------------+---------------+-------------+
| ancestor_id | descendant_id | path_length |
+-------------+---------------+-------------+
| 1 | 1 | 0 |
| 1 | 2 | 1 |
| 1 | 3 | 1 |
| 1 | 4 | 2 |
| 1 | 5 | 3 |
| 1 | 6 | 4 |
| 2 | 2 | 0 |
| 2 | 4 | 1 |
| 2 | 5 | 2 |
| 2 | 6 | 3 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 4 | 5 | 1 |
| 4 | 6 | 2 |
| 5 | 5 | 0 |
| 5 | 6 | 1 |
| 6 | 6 | 0 |
+-------------+---------------+-------------+
This is table buy
+--------+--------+
| userid | amount |
+--------+--------+
| 2 | 2000 |
| 4 | 6000 |
| 6 | 7000 |
| 1 | 7000 |
SQL code
SELECT a.*
FROM
( SELECT userid
FROM webineh_user_buys
GROUP BY userid
HAVING SUM(amount) >= 1000
) AS buys_d
JOIN
webineh_prefix_nodes_paths AS a
ON a.descendant_id = buys_d.userid
JOIN
(
SELECT userid
FROM webineh_user_buys
GROUP BY userid
HAVING SUM(amount) >= 1000
) AS buys_a on (a.ancestor_id = buys_a.userid )
JOIN
( SELECT descendant_id
, MAX(path_length) path_length
FROM webineh_prefix_nodes_paths
where a.ancestor_id = ancestor_id
GROUP
BY descendant_id
) b
ON b.descendant_id = a.descendant_id
AND b.path_length = a.path_length
GROUP BY a.descendant_id, a.ancestor_id
I need get max path_length where ancestor_id have At least 1000 amount buy but have error in where in subquery where a.ancestor_id = ancestor_id error code
1054 - Unknown column 'a.ancestor_id' in 'where clause'
I add SQLFidle demo.
You could use this query:
select m.userid as descendant,
p.ancestor_id,
p.path_length
from (
select b1.userid,
min(case when b2.amount >= 1000
then p.path_length
end) as path_length
from (select userid, sum(amount) amount
from webineh_user_buys
group by userid
having sum(amount) >= 1000
) as b1
left join webineh_prefix_nodes_paths p
on p.descendant_id = b1.userid
and p.path_length > 0
left join (select userid, sum(amount) amount
from webineh_user_buys
group by userid) as b2
on p.ancestor_id = b2.userid
group by b1.userid
) as m
left join webineh_prefix_nodes_paths p
on p.descendant_id = m.userid
and p.path_length = m.path_length
order by m.userid
Output for sample data in the question:
| userid | ancestor_id | path_length |
|--------|-------------|-------------|
| 1 | (null) | (null) |
| 2 | 1 | 1 |
| 4 | 2 | 1 |
| 6 | 4 | 2 |
SQL fiddle

SQL SELECT SUM from two tables and group by

I have two tables (PO and GRN).
I want to get:
[This is what I am doing:][1] http://sqlfiddle.com/#!9/db000/2
I get these results (wrong po_qty , GRN_qty and GRN_balance ).
What I am expecting is:
| Item | PONO | po_qty | GRN_qty | GRN_balance |
|------|------|--------|---------|-------------|
| A | po1 | 70 | 65 | 5 |
| B | po1 | 50 | 0 | 50 |
| C | po2 | 10 | 5 | 5 |
| D | po3 | 20 | 0 | 20 |
| A | po4 | 15 | 10 | 5 |
Here is a way of doing it
select
p.Item,
p.PONO,
sum(p.Qty) as po_qty,
coalesce(g.GRN_qty,0) ,
sum(p.Qty) - coalesce(g.GRN_qty,0) as GRN_balance
from PO p
left join (
select PONO,Item,sum(Qty) as GRN_qty from GRN
group by PONO,Item
)g
on g.PONO = p.PONO and g.Item = p.Item
group by p.Item,p.PONO
order by p.PONO
http://sqlfiddle.com/#!9/db000/30
I modified your SQL. Please execute and see
SELECT PO.Item,PO.PONO,
PO.Qty as po_qty,
GRN.Qty as GRN_qty,
PO.Qty- GRN.Qty as GRN_balance
from PO,GRN
group by PO.Item
Thank you..