Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have exhausted all of my options. I cannot understand where I am going wrong with this. Please help me. I can not take much more headbanging. Here is where I am at...
Below is an explanation of my table structure.
locations_management table
contains data linking the locations_management_id, season_id, location_id and other unneeded information together
orders table
contains data about the order including the location_management_id and the order_id as well as other unneeded information
orders_products table
product data linked to the orders by order_id. This table only uses these columns: order_product_id, order_id, product_id, piece_qty
orders_adjustments table
used to track any adjustments to the inv_shipped. This table uses the order_id, product_id, piece_qty columns
Here is where I am at today. The query below pulls data from the tables above.
Basically I am asking for the location_management_id(s) from the locations_management table WHERE season_id = 12 AND location_id = 35. There can be more than one possible location_management_id that fits both the season_id and location_id. I then need to find the orders that match these location_management_id(s). Once the orders are found, I need to use the order_id(s) to find the products associated to them in the orders_products table.
This query does exactly that but when I take it a step further to combine/SUM the
piece_qty for a total inv_shipped, crazy things happen to the numbers.
SELECT
locations_management.season_id,
locations_management.location_id,
orders.order_id,
orders_products.product_id,
IFNULL((orders_products.piece_qty), 0) AS inv_shipped,
IFNULL((orders_adjustments.piece_qty), 0) AS inv_adjustments
FROM
locations_management
JOIN orders USING (location_management_id)
LEFT JOIN orders_products USING (order_id)
LEFT JOIN orders_adjustments ON (orders_adjustments.order_id = orders_products.order_id) AND (orders_adjustments.product_id = orders_products.product_id)
WHERE
locations_management.season_id = 12 AND locations_management.location_id = 35
GROUP BY
product_id, orders_products.order_id
When I run the query above, this is what I get...
season_id location_id order_id product_id inv_shipped inv_adjustments
12 35 2127 1 220 0
12 35 2194 1 160 0
12 35 2127 3 312 0
12 35 2127 4 24 0
12 35 2127 5 180 0
12 35 2194 5 24 0
12 35 2127 7 144 0
12 35 2127 7 24 0
This is exactly what I would expect to get. Multiple order_id's grouped by the product_id and all the data is accurate. So now here becomes the problem. I want to add/SUM the product_id's together when they match and have a combined inv_shipped. So product_id 1 would now total 380 for inv_shipped.
When I take the same query from above and I add SUM to the inv_shipped and inv_adjustments (as seen below), I get this data output below. Notice how some of the values have doubled but also the matching product_id rows are not combined.
IFNULL(SUM(orders_products.piece_qty), 0) AS inv_shipped,
IFNULL(SUM(orders_adjustments.piece_qty), 0) AS inv_adjustments
season_id location_id order_id product_id inv_shipped inv_adjustments
12 35 2127 1 440 0
12 35 2194 1 160 0
12 35 2127 3 624 0
12 35 2127 4 48 0
12 35 2127 5 360 0
12 35 2194 5 24 0
12 35 2127 7 288 0
12 35 2127 7 24 0
If I change the GROUP BY to product_id only, I get the follow data:
GROUP BY product_id
season_id location_id order_id product_id inv_shipped inv_adjustments
12 35 2127 1 600 0
12 35 2127 3 624 0
12 35 2127 4 48 0
12 35 2127 5 384 0
12 35 2127 7 312 0
Again these inv_shipped totals are not correct. So where am I going wrong?
------------------------------------ Suggestions ------------------------------------
This query below was suggested but the data output for the inv_shipped is not added correctly either.
SELECT
locations_management.season_id,
locations_management.location_id,
orders.order_id,
products.product_id,
products.inv_shipped
FROM
locations_management
JOIN (SELECT location_management_id, order_id FROM orders group by order_id) AS orders ON orders.location_management_id = locations_management.location_management_id
JOIN (SELECT order_id, product_id, IFNULL(SUM(piece_qty), 0) AS inv_shipped FROM orders_products GROUP BY order_id, product_id) AS products ON products.order_id = orders.order_id
WHERE
locations_management.season_id = 12 AND locations_management.location_id = 35
ORDER BY
product_id, order_id
season_id location_id order_id product_id inv_shipped inv_adjustments
12 35 2127 1 440 0
12 35 2194 1 160 0
12 35 2127 3 624 0
12 35 2127 4 48 0
12 35 2127 5 360 0
12 35 2194 5 24 0
12 35 2127 7 288 0
12 35 2127 7 24 0
First, find the root of the issue. What changes in between the correct and incorrect information?
Let's take a look at your second query. From what I can see, there are three things that changes:
You've joined with another sub-query.
You've added a SUM operation.
You've added a GROUP BY.
Nest step is to try with removing SUM and GROUP BY, like this:
SELECT
locations_management.season_id AS season_id,
locations_management.location_id AS location_id,
orders.order_id AS order_id,
products.product_id AS product_id,
products.piece_qty
FROM
locations_management
JOIN (SELECT location_management_id, order_id FROM orders group by order_id) AS orders ON orders.location_management_id = locations_management.location_management_id
JOIN (SELECT order_id, product_id, piece_qty FROM orders_products) AS products ON products.order_id = orders.order_id
WHERE
locations_management.season_id = 12 AND locations_management.location_id = 35
I assume that each product_id will return two (or more) rows. That's probably because of your second JOIN have two (or more) rows for order_id in orders_products table; it seems obvious because the first sub-query for table orders have group by order_id. So, now to quickly fix this, you need to do the SUM inside the second sub-query instead. Something like this:
SELECT
locations_management.season_id AS season_id,
locations_management.location_id AS location_id,
orders.order_id AS order_id,
products.product_id AS product_id,
products.inv_shipped
FROM
locations_management
JOIN (SELECT location_management_id, order_id FROM orders group by order_id) AS orders ON orders.location_management_id = locations_management.location_management_id
JOIN (SELECT order_id, product_id, IFNULL(SUM(products.piece_qty), 0) AS inv_shipped FROM orders_products GROUP BY order_id, product_id) AS products ON products.order_id = orders.order_id
WHERE
locations_management.season_id = 12 AND locations_management.location_id = 35;
This might return you the correct result however I personally will write the query like this:
SELECT lm.season_id, lm.location_id, o.order_id , p.product_id, p.inv_shipped
FROM locations_management AS lm
JOIN (SELECT location_management_id, order_id
FROM orders
GROUP BY location_management_id,order_id) AS o
ON o.location_management_id = lm.location_management_id
JOIN (SELECT order_id, product_id, IFNULL(SUM(products.piece_qty), 0) AS inv_shipped
FROM orders_products
GROUP BY order_id, product_id) AS p
ON p.order_id = o.order_id
WHERE
lm.season_id = 12 AND lm.location_id = 35;
You don't need to set alias if your alias is the same as column name; for example lm.season_id AS season_id. If you remove .. AS season_id, the column will be recognized as season_id nonetheless. You won't see it as lm.season_id.. well at least for most tools that I know of. Also, I personally think aliases are meant to shorten long table or column names but "to each their own".
GROUP BY should include all the non-aggregated column(s) in SELECT. Of course, if the sql_mode=only_full_group_by is turned off, you can run the query but the correct setting should be ON. You can read more of the reason why here.
With the additional columns added in GROUP BY, this query might not return the result you once had. That's depending on you data and if that happen, I suggest you edit your question and add a Minimal, reproducible example. At the moment, we're only seeing queries and no example table/data to work with. Its better if you can create a fiddle with a few rows of data.
I don't see the need for those nested subqueries. And if you want one row per order and product, then aggregation may not be necessary.
You seem to want Doesn't this do what you want?
select lm.season_id, lm.location_id,
op.order_id, op.product_id, op.piece_qty as inv_shipped
from locations_management lm
inner join orders o on o.location_management_id = lm.location_management_id
inner join order_products op on op.order_id = o.order_id
where lm.season_id = 12 and lm.location_id = 35
Or if you want one row per product:
select lm.season_id, lm.location_id,
op.product_id, coalesce(sum(op.piece_qty), 0) as inv_shipped
from locations_management lm
inner join orders o on o.location_management_id = lm.location_management_id
left join order_products op on op.order_id = o.order_id
where lm.season_id = 12 and lm.location_id = 35
group by lm.season_id, lm.location_id, op.product_id
Related
I have 2 tables.
table customer have. id , name , age
table order have . id, customer_id , order_amount , order date.
I want to show all name from customer table and sum of order amount from order table according to customer.
customer_id
Name
age
1
Alice
24
2
Bob
52
3
Carol
45
4
Dave
51
order_id
customer_id
order_amount
order_date
1
2
50
2012-4-5
2
1
27
2012-8-1
3
2
12
2013-5-20
4
4
25
2014-1-25
5
4
30
2014-5-30
6
1
20
2014-6-22
EDIT
I tried this but it gives me only bob and sum of all columns instead of separate sum of customers
SELECT customers.name, SUM(orders.order_amount) FROM `orders` INNER JOIN customers WHERE orders.customer_id = customers.customer_id;
Joining condition must be on ON clause, not in WHERE.
You must specify for what group the sum must be calculated.
SELECT customers.name, SUM(orders.order_amount)
FROM `orders`
INNER JOIN customers ON orders.customer_id = customers.customer_id
GROUP BY customers.name;
I am new with mysql and working to change a store application to make it have two stock. I created a table to store stock quantity:
Then I plan to create a view with stock quantity, per store, per SKU. I using the following query:
SELECT
`stockList`.`sku`,
SUM(A.`stockQty`) AS 'store1',
SUM(B.`stockQty`) AS 'store2',
SUM(`stockList`.`stockQty`) AS 'total'
FROM `stockList`
LEFT JOIN (
SELECT * FROM `stockList` WHERE `idStock`=1
) AS A
ON `stockList`.`sku`=A.`sku`
LEFT JOIN (
SELECT * FROM `stockList` WHERE `idStock`=2
) AS B
ON `stockList`.`sku`=B.`sku`
GROUP BY `stockList`.`sku`
Per resulting table, calculation is not proper and I could not identify the logic:
SKU 43 should show for store1 = 9 and for store2 = 10, total = 19. This is what they show if I execute the select queries alone. Please, let me know if I misunderstood how this sum logic works.
You might to use SUM on subquery to calculate Totle price by sku
LEFT JOIN may make some fields not match causing NULL so use IFNULL to preset value 0
You can try this.
SELECT
T.sku,
SUM(T.stockQty) as totle,
IFNULL(A.`store1`,0) AS `store1`,
IFNULL(B.`store2`,0) AS `store2`
FROM `stockList` AS T
LEFT JOIN
(
SELECT sku,SUM(`stockQty`) as `store1`
FROM `stockList`
WHERE `idStock`=1
GROUP BY sku
) as A ON A.sku = T.sku
LEFT JOIN
(
SELECT sku,SUM(`stockQty`) as `store2`
FROM `stockList`
WHERE `idStock`=2
GROUP BY sku
) AS B ON T.sku =B.sku
GROUP BY T.sku
sqlfiddle
Your query is much more complicated than it needs to be. You can just do this:
SELECT
sku,
SUM(stockQty) as total,
SUM(IF(idStock=1,stockQty,0)) AS `store1`,
SUM(IF(idStock=2,stockQty,0)) AS `store2`
FROM `stockList`
GROUP BY sku
Output:
sku total store1 store2
36 10 10 0
37 3 3 0
38 4 4 0
39 3 3 0
40 10 10 0
41 12 12 0
42 12 12 0
43 19 9 10
I need to perform a COUNT on a quite a big query, where one of the joined tables has a one-to-many relationship. This is throwing off my result as all data is being multiplied by the number of times an item is repeated in the 'many' side of the one-to-many table.
This is a shortened version of the query showing only the relevant portion to highlight the issue:
SELECT COUNT(trimtype) FROM versiontrim
INNER JOIN trims USING (trim_id)
INNER JOIN prices USING(version_id)
INNER JOIN m_versions USING(version_id)
WHERE trimtype IN('sec', 'help') AND price BETWEEN 200001 AND 210000
GROUP BY version_id
All tables are quite straighforward except m_versions that has the one-to-many relationship and looks like this:
version_id serv_id
1 1
1 2
1 3
1 4
1 5
.... and so on
The expected result of the query is :
version_id COUNT(trimtype)
44 9
54 7
69 9
214 10
216 6
282 1
290 10
Instead I am getting this,ie, all counts multiplied by 5 which is the number of times version_id is repeated in the m_versions table:
version_id COUNT(trimtype)
44 45
54 35
69 45
214 50
216 30
282 5
290 50
How to avoid this behavior?
Thanks
It matches to multiple records on table m_version that is why you are getting invalid result. Try wrapping it a subquery,
INNER JOIN (SELECT DISTINCT version_id FROM m_versions) m USING(version_id)
UPDATE
So the full query will look like this,
SELECT version_id, COUNT(trimtype)
FROM versiontrim
INNER JOIN trims USING (trim_id)
INNER JOIN prices USING(version_id)
INNER JOIN (SELECT DISTINCT version_id FROM m_versions) m USING(version_id)
WHERE trimtype IN('sec', 'help') AND price BETWEEN 200001 AND 210000
GROUP BY version_id
SELECT
C.CompanyId,
CompanyName,
Server,
ServerUsers,
ServerUptime,
ServerHostName,
ServerType
FROM
CUSTOMERS AS C
INNER JOIN
USERS ON C.CompanyId = USERS.CompanyId
WHERE
USERS.UserEmail='matt' AND
USERS.UserPin='5153' AND
(SELECT Status FROM 4321_BlackBerryServices LIMIT 0,1)
LIMIT 0, 8
Currently my table is below
4321 T1 Solutions EXCH-01 392 47 days, 17 min exch01.myCorp.com ExchangeServices
4321 T1 Solutions EXCH-02 685 47 days, 17 min exch02.myCorp.com ExchangeServices
4321 T1 Solutions Lync-01 368 47 days, 17 min lync01.myCorp.com LyncServices
4321 T1 Solutions Lync-02 890 458 days, 58 min lync02.myCorp.com LyncServices
What i would like to do is add the last result from Status FROM 4321_BlackBerryServices so i would want to add the latest status for each server in my table
how is this possible ?
If I understand what you need, try this:
SELECT
C.CompanyId, CompanyName, Server, ServerUsers,
ServerUptime, ServerHostName, ServerType,
(SELECT Status FROM 4321_BlackBerryServices
ORDER BY field_you_know DESC LIMIT 0,1) AS BBS_Status
FROM CUSTOMERS AS C
INNER JOIN USERS
ON C.CompanyId = USERS.CompanyId
AND USERS.UserEmail = 'matt'
AND USERS.UserPin = '5153'
LIMIT 0, 8
In my query field_you_know field is the one you know you can sort the table to take the last one.
I was successful in writing the query that lists salesmen that did sell to a particular customer, but not those that have not. I suspect it is because the same salesmen that sold to the specific customer, also sold to other customers.
select a.name from salesperson a inner join orders b on
a.salesperson_id = b.salesperson_id where cust_id="4";
I was thinking that modifying the same query like this would do the trick:
.... a.salesperson_id <> b.salesperson_id where cust_id="4";
But the result lists all the salesmen. This is most likely due to the fact that the same salesmen that were returned in the original query, also sold to other customers
The 3 tables look like this:
Salesperson table
salesperson_ID, Name, Age, Salary
1 Abe 61 140000
2 Bob 34 44000
5 Chris 34 40000
7 Dan 41 52000
8 Ken 57 115000
11 Joe 38 38000
Customer table
cust_ID, Name, City Industry Type
4 faralon sacramento H
6 Apple cupertino S
7 Honda NY B
9 Kolb Oshkosh B
Orders table
Number, Order_date, cust_id, salesperson_id, Amount
10 8/2/1996 4 2 540
20 1/30/1999 4 8 1800
30 7/14/1995 9 1 460
40 1/29/1998 7 2 2400
50 2/3/1998 6 7 600
60 3/2/1998 6 7 720
70 5/6/1998 9 7 150
Any help would be greatly appreciated. ~Alpinehyker
You can do something like this:
select a.name from salesperson a
left join orders b on a.salesperson_id = b.salesperson_id and b.cust_id="4"
where b.Number is null
So, get all salepersons, left join to orders for customer 4, and return only rows where there is no such order.
I am assuming that Number is the primary key for Orders, or at least not null.
All salespeople who have NOT sold to customer_ID 4:
SELECT s.Name FROM Salesperson AS s
LEFT JOIN Orders AS o
ON s.salesperson_ID = o.salesperson_ID
WHERE o.customer_ID <> 4
GROUP BY o.salesperson_ID;
Perhaps this will work
SELECT
s.*
FROM `Salesperson` AS s
LEFT JOIN `Orders` AS o ON o.`salesperson_id` = s.`salesperson_ID`
WHERE
o.`cust_id` NOT IN (4)
GROUP BY s.`salesperson_ID`;
Answer to your 2nd question:
SELECT
COUNT(*) AS num_of_orders
,s.`Name`
FROM `Salesperson` AS s
LEFT JOIN `Orders` AS o ON o.`salesperson_id` = s.`salesperson_ID`
GROUP BY s.`salesperson_ID`
HAVING num_of_orders >= 2;
...and 3rd question. (assuming you have your highAchiever table ready)
INSERT INTO `highAchiever`
(`Name`,`Age`)
SELECT
`Name`
,`Age`
FROM `Salesperson`
WHERE
`Salary` >= 100000;