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;
Related
these are my tables
ORDER_ITEMS
+----------+--------+-----------------+------------+
| order_id |item_id | item_name | quantity |
+----------+--------+-----------------+------------+
| 1 | 1 | coffee | 2 |
| 2 | 2 | shake | 2 |
| 2 | 3 | icecream | 3 |
+----------+--------+-----------------+------------+
PRODUCT_INGREDIENT:
+--------+-----------------+--------+
|item_id | ingredient_id | amount |
+--------+-----------------+--------+
| 1 | 123 | 10 |
| 1 | 124 | 15 |
| 2 | 125 | 10 |
| 2 | 124 | 15 |
| 2 | 123 | 10 |
| 2 | 126 | 15 |
| 3 | 124 | 15 |
| 3 | 123 | 10 |
| 3 | 126 | 15 |
+--------+-----------------+--------+
INVENTORY:
+--------+-----------------+--------+
| id | ingredient_id | amount |
+--------+-----------------+--------+
| 1 | 123 | 80 |
| 2 | 124 | 70 |
| 3 | 125 | 100 |
| 4 | 126 | 100 |
+--------+-----------------+--------+
the sql I have is working but I need to multiply the (amount)column in PRODUCT_INGREDIENT table to the column(quantity) in ORDER_ITEMS table
before
this is the sql statement
UPDATE inventory i
INNER JOIN (
SELECT p.ingredient_id, sum(p.amount) amount
FROM product_ingredient p
INNER JOIN order_items o on o.item_id = p.item_id
WHERE o.order_id = 1
GROUP BY p.ingredient_id
) p ON i.ingredient_id = p.ingredient_id
SET i.amount = i.amount - p.amount
I want my inventory to look like this after query
INVENTORY:
+--------+-----------------+--------+
| id | ingredient_id | amount |
+--------+-----------------+--------+
| 1 | 123 | 100 |
| 2 | 124 | 100 |
| 3 | 125 | 100 |
| 4 | 126 | 100 |
+--------+-----------------+--------+
Looking to your data sample seems you need add the result of the subquery
UPDATE inventory i
INNER JOIN (
select p.ingredient_id, sum(p.amount*o.quantity) amount
from product_ingredient p
INNER JOIN order_items o on o.item_id = p.item_id
WHERE o.order_id = 1
GROUP BY p.ingredient_id
) p ON i.ingredient_id = p.ingredient_id
SET i.amount = i.amount + p.amount
You can use such an UPDATE statement :
UPDATE inventory i
INNER JOIN (
SELECT p.ingredient_id, sum(p.amount*o.quantity) amount
FROM product_ingredient p
INNER JOIN order_items o on o.item_id = p.item_id
WHERE o.order_id = 1
GROUP BY p.ingredient_id
) p ON i.ingredient_id = p.ingredient_id
SET i.amount = i.amount + p.amount
Demo
Only ingredient_id 123 and 124 are matched for the whole query. So, only they're updated.
I have six tables in the database, all tables are relative to each other and want to show records in one table.
Following are my tables:
1) mls_stores
*----------------------------*
| store_id | store_title |
*----------------------------*
| 1001 | ajmar-jaipur |
| 1002 | dwarka-delhi |
*----------------------------*
2) mls_category
*-------------------------------------------*
| cat_no | store_id | cat_value | cat_type |
*-------------------------------------------*
| 20 | 1001 | 1 | running |
| 21 | 1001 | 4 | cycling |
| 22 | 1002 | 1 | running |
| 23 | 1002 | 2 | swmining |
*-------------------------------------------*
3) mls_points_matrix
*----------------------------------------*
| store_id | value_per_point | maxpoint |
*----------------------------------------*
| 1001 | 1 | 10 |
| 1001 | 2 | 20 |
| 1002 | 1 | 20 |
| 1002 | 4 | 30 |
*----------------------------------------*
4) mls_user
*--------------------------*
| id | store_id | name |
*--------------------------*
| 1 | 1001 | sandeep |
| 2 | 1001 | jagveer |
| 3 | 1002 | gagan |
*--------------------------*
5) bonus_points
*---------------------------------------------------*
| user_id | store_id | bonus_points | bonus_type |
*---------------------------------------------------*
| 1 | 1001 | 10 | fixed |
| 3 | 1002 | 2 | % |
*---------------------------------------------------*
6) mls_entry
*-------------------------------------------------------*
| user_id | store_id | category | distance | status |
*-------------------------------------------------------*
| 1 | 1001 | 20 | 10 | approved |
| 1 | 1001 | 21 | 40 | approved |
| 1 | 1001 | 20 | 5 | reject |
| 2 | 1001 | 21 | 40 | approved |
| 3 | 1002 | 22 | 10 | approved |
| 3 | 1002 | 23 | 20 | approved |
*-------------------------------------------------------*
Now I want output as below:
*-----------------------------------------------------------------------------------*
| Name | Entries | Points Earned | Bonus Points | Total Points | Total Amount |
*-----------------------------------------------------------------------------------*
| Sandeep | running(1) | 20 | 10 | 30 | 60 |
| | cycling(1) | | | | |
*-----------------------------------------------------------------------------------*
| Jagveer | cycling(1) | 10 | 0 | 10 | 10 |
*-----------------------------------------------------------------------------------*
I am using following code:
SELECT
u.name,
ROUND(COALESCE(t1.points, 0)) AS points,
ROUND(COALESCE(b.bonus_points, 0)) AS bonus_points,
ROUND(COALESCE(t1.points, 0) + COALESCE(b.bonus_points, 0)) AS total_points
FROM mls_user u
LEFT JOIN
(
SELECT e.user_id, e.status, SUM(e.distance / c.cat_value) AS points
FROM mls_entry e
INNER JOIN mls_category c
ON e.store_id = c.store_id AND e.category = c.cat_no
GROUP BY e.user_id
HAVING e.status='approved'
) t1
ON u.id = t1.user_id
LEFT JOIN bonus_points b
ON u.id = b.user_id
WHERE u.store_id = '1001'
ORDER BY
total_points DESC
This SQL query giving me Point earned, bonus points and total points, But I am not able to find Entries And Total Amount and it is giving me wrong Point calculation for Sandeep, As per data one entry is rejected. so it should be 20, not 25.
My total amount will be for Sandeep 30X2(it is coming from point matrix) = 60
same like for jagveer, the total amount for jagveer 10X1 = 10.
I have created tables in DEMO
Try below :
SELECT
u.name,
ROUND(COALESCE(t1.points, 0)) AS points,
ROUND(COALESCE(b.bonus_points, 0)) AS bonus_points,
ROUND(COALESCE(t1.points, 0) + COALESCE(b.bonus_points, 0)) AS total_points,
ROUND(COALESCE(t1.points, 0) + COALESCE(b.bonus_points, 0)) * t1.countId as total_amount,
group_concat(t1.EntriesConcat) as Entries
FROM mls_user u
LEFT JOIN
(
SELECT e.user_id, e.status, SUM(e.distance / c.cat_value) AS points,
concat(c.cat_type, '(',count(e.user_id), ')' ) as EntriesConcat,
count(e.user_id) as countId -- it returns count of records according to group by part
FROM mls_entry e
INNER JOIN mls_category c
ON e.store_id = c.store_id AND e.category = c.cat_no
-- remove HAVING and use WHERE clause
WHERE e.status='approved'
GROUP BY e.user_id
) t1 ON u.id = t1.user_id
LEFT JOIN bonus_points b ON u.id = b.user_id
WHERE u.store_id = '1001'
ORDER BY total_points DESC
group_concat of mysql is useful to concatinating values on Group By
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)
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
Hi I have doubt in sql server
dept
+---------+--------+
| deptkey | deptno |
+---------+--------+
| 1 | 100 |
| 2 | 101 |
| 3 | -1 |
+---------+--------+
loc
+--------+-------+
| lockey | locid |
+--------+-------+
| 1 | 200 |
| 2 | 201 |
| 3 | -1 |
+--------+-------+
trans
+----+--------+-------+------+
| id | deptno | locid | Name |
+----+--------+-------+------+
| 1 | 100 | 201 | abc |
| 2 | 101 | 203 | def |
| 3 | 103 | 200 | rav |
| 4 | 105 | 204 | jai |
| 1 | 101 | 200 | kal |
| 4 | 100 | 206 | lo |
+----+--------+-------+------+
here tran deptno= dept.deptno then corresponding key values bring if not match then we need to unmatched deptno assign -1 and corresponding key need to retrive
similar tran locid=loc.locid
based on above tables I want output like below
+----+------+---------+--------+
| id | Name | deptkey | lockey |
+----+------+---------+--------+
| 1 | abc | 1 | 2 |
| 2 | def | 2 | 3 |
| 3 | rav | 3 | 1 |
| 4 | jai | 3 | 3 |
| 1 | kal | 2 | 1 |
| 4 | lo | 1 | 3 |
+----+------+---------+--------+
I tried like below query
SELECT a.[id],a.name ,b.deptkey,c.lockey
FROM [trans] a left join dept b on a.deptno=b.deptno
left join loc c on a.locid=c.locid
above query not given expected result can you please tell me how to write query to achive this task in sql server
SELECT a.[id],a.name ,
(CASE WHEN b.deptkey IS NULL THEN (select deptkey from DEPT WHERE DeptNo = -1)
ELSE b.deptkey END) AS 'deptkey',
(CASE WHEN c.lockey IS NULL THEN (select LocKey from LOC WHERE LocId = -1)
ELSE c.lockey END) AS 'lockey '
FROM [trans] a left join dept b on a.deptno=b.deptno
left join loc c on a.locid=c.locid
http://www.sqlfiddle.com/#!3/389463/2
SELECT a.[id],a.name ,b.deptkey,c.lockey
FROM [trans] a left join dept b on isnull(a.deptno,-1)=isnull(b.deptno,-1)
left join loc c on a.locid=c.locid
try with this...
SELECT
a.[id]
, a.name
, ISNULL(b.deptkey,-1) AS [deptkey]
, ISNULL(b.lockey,-1) AS [lockey]
FROM [trans] a
left join dept b
on a.deptno = b.deptno
left join loc c
on a.locid = c.locid
When the value is not found ISNULL, change the result to -1 instead of NULL. You can just change the -1 with any default value you prefer as unmatched.
OR if you want a query driven default value (get the last record as the default value). You can change your script as presented below.
SELECT
a.[id]
, a.name
, ISNULL(b.deptkey,(SELECT TOP 1 deptno from dept ORDER BY deptkey DESC)) AS [deptkey]
, ISNULL(b.lockey,(SELECT TOP 1 locid from loc ORDER BY lockey DESC)) AS [lockey]
FROM [trans] a
left join dept b
on a.deptno = b.deptno
left join loc c
on a.locid = c.locid