selecting complex query into an exsiting column - mysql

I have a table, one column of which is VERY dependant on a bunch of other tables
i can't alter the table, and i can't change the name of the parameter that is used
this is my query :
select *,(select sum(itemQuantity*(select itemPrice from Items where
Items.itemID=OrderItems.itemID)) from OrderItems
where OrderItems.orderNumber=Orders.orderNumber) as orderValue,
(select sum(itemQuantity) from OrderItems where OrderItems.orderNumber=Orders.orderNumber)
as orderItemQuantity from Orders WHERE Orders.customerId =1 AND Orders.beenSupplied =1
and this is the result of this query:
as you can see, i have the column "orderValue" twice
the first orderValue is the original column from the Orders table, and the second orderValue is from the "as" clause in the query
how do i merge the two columns and have the output of the query in it, and not the 0 that constantly gets inserted ?
EDIT:
table structures:

Rather than using SELECT *, explicitly list the columns (from your Orders table) that you wish to select.
You can also avoid using (the highly inefficient) correlated subqueries by joining the tables in the outermost query and then grouping each order.
SELECT Orders.orderNumber,
Orders.customerId,
Orders.orderDate,
Orders.beenSupplied,
Orders.purchaseDate,
SUM(OrderItems.itemQuantity * Items.itemPrice) AS orderValue,
SUM(OrderItems.itemQuantity) AS orderItemQuantity
FROM Orders
JOIN OrderItems USING (orderNumber)
JOIN Items USING (itemID)
WHERE Orders.customerId = 1
AND Orders.beenSupplied = 1
GROUP BY Orders.orderNumber

Related

Creating a percentage column on a table made from an inner join

I have two tables Orders and RMA. I wrote this command to return an inner join between the two tables. OrderID is the primary key of Orders and foreign key of RMA.
SELECT Orders.SKU, COUNT(*) AS Frequency
FROM Orders
INNER JOIN RMA ON Orders.OrderID = RMA.OrderID
GROUP BY Orders.SKU
ORDER BY COUNT(*) DESC;
This select statement returns a table with one column containing SKU values and one column containing the number of times each SKU value appears in the data. My goal is to create a third column that includes a percent that represents the frequency of each SKU value.
(disclaimer: I'm new to mysql, so if there's more information needed for this question, I am happy to provide it. Thanks!)
You must divide COUNT(*) with the total number of rows in RMA:
SELECT Orders.SKU,
COUNT(*) AS Frequency,
COUNT(*) / (SELECT COUNT(*) FROM RMA) AS percent
FROM Orders INNER JOIN RMA
ON Orders.OrderID = RMA.OrderID
GROUP BY Orders.SKU
ORDER BY Frequency DESC;

Please explain differences between 2 SQL statements

I have wrote 2 SQL statements.
SELECT
customers.CustomerID,
orders.OrderID
FROM customers LEFT JOIN orders ON customers.CustomerID =
orders.CustomerID AND orders.EmployeeID=4
WHERE orders.OrderID IS NULL;
And
SELECT
customers.CustomerID,
orders.OrderID
FROM customers LEFT JOIN orders ON customers.CustomerID =
orders.CustomerID AND orders.EmployeeID=4 AND orders.OrderID IS NULL;
The 1st one returns 16 entries, which is correct (per the solution). The 2nd one returns 91 entries. I am using Northwind for mysql version. I read from somewhere that placing condition in JOIN statement is equivalent to doing that in WHERE statement. However, here I can see the difference.
This is to do with the order execution on the statements and the fact you’re using a LEFT JOIN.
A LEFT JOIN will keep all the values from the left side intact, combining only values from the right side that match conditions.
A WHERE clause operates on the query as a whole (in this case).
Query 1:
Get all values from left table
Join on any values from the right table that match conditions
Filter the joined output based on the where condition
Query 2:
Get all values from the left table
Join on any values from the right table that match conditions
The only time a WHERE is really analogous to a JOIN is something like a INNER JOIN, which gets only the relevant values from both left and right sides. I think at least, it has been a while since I flexed the SQL muscles.
Edit - count the number of rows (nothing else) in your customers table, it should return 91 as well.
The second query will return more rows. Why? Read on:
Second query
The second query will match orders rows to customers rows using the predicate:
customers.CustomerID = orders.CustomerID AND orders.EmployeeID=4 AND orders.OrderID IS NULL
Unmatched customers rows will always show up in the result.
First query
Now, the first query will match orders rows to customers rows using the predicate:
customers.CustomerID = orders.CustomerID AND orders.EmployeeID=4
Then it will filter out rows where orders.OrderID is null, removing customer rows that do not fullfil this last predicate, therefore producing less rows. Unmatched customers rows may not show up in the result.
Example:
create table customers (
CustomerId int
);
create table orders (
OrderId int,
CustomerId int,
EmployeeId int
);
insert into customers (CustomerId) values (1), (2), (3);
insert into orders (OrderId, CustomerId, EmployeeId) values
(1001, 1, 3),
(1002, 1, 4),
(1003, 2, 1);
The first query returns:
CustomerId OrderId
---------- ----------------
2 <null>
3 <null>
while the second query returns:
CustomerId OrderId
---------- ----------------
1 <null>
2 <null>
3 <null>
This could be because of the order in which the Sql query runs
FROM and JOIN s. The FROM clause, and subsequent JOIN s are first executed then
WHERE and lastly SELECT.
In second case all the join conditions ran together but in the first case the where clause made the difference after joining the data and filtering not at the same time but as a whole after joining.

How to join a derived table

I have a complex query which results in a table which includes a time column. There are always two rows with the same time:
The result also contains a value column. The value of two rows with the same time is always different.
I now want to extend the query to join the rows with the same time together. So my thought was to join the derived table like this:
SELECT A.time, A.value AS valueA, B.value as valueB FROM
(
OLD_QUERY
) AS A INNER JOIN A AS B ON
A.time=B.time AND
A.value <> B.value;
However, the JOIN A AS B part of the query does not work. A is not recognized as the derived table. MySQL is searching for a table A in the database and does not find it.
So the question is: How can I join a derived table?
You cannot join a single reference to a table (or subquery) to itself; a subquery must be repeated.
Example: You cannot even do
SELECT A.* FROM sometable AS A INNER JOIN A ...
The A after the INNER JOIN is invalid unless you actually have a real table called A.
You can insert the subquery's results into another table, and use that; but it cannot be a true TEMPORARY table, as those cannot be joined to themselves or referenced twice at all in almost any query. _By referenced twice, I mean joined, unioned, used as an "WHERE IN" subquery when it is already referenced in the FROM.
If nothing else distinguishes the rows, you can just use aggregation to get the two values:
select time, min(value), max(value)
from (<your query here>) a
group by time;
In MySQL 8+, you can use a cte:
with a as (
<your query here>
)
select a1.time, a1.value, a2.value
from a a1 join
a a2
on a1.time = a2.time and a1.value <> a2.value;

MYSQL - Count and GROUP from table1 and get info from table2

I am struggling with a MySQL query which I cant get to work as I want.
In table1 I have co_id, name, code, product, logindate.
in table2 I have pr_id, productname, productno, price.
I want to count and group the PRODUCT from table1, so I can see how many that have picked for example product 1,2,3 etc.
But when I list the result on the page I will need productname, and productno for each id number in the GROUP search. table1.product is joined with table2.pr_id
This is what I have so far, but I think I am missing something with INNER JOIN or similar, right?
SELECT
codes.pickedgift,
products.productno,
products.productname,
COUNT(codes.pickedgift) as num
FROM
codes,
products
GROUP BY codes.pickedgift
ORDER BY codes.pickedgift
you missing the join condition, when you join 2 tables you should link primary key in table1 to its foreign key in another table, so your query can be:
SELECT
codes.pickedgift,
products.productno,
products.productname,
COUNT(codes.pickedgift) as num
FROM
codes INNER JOIN products ON codes.product = products.pr_id
GROUP BY codes.pickedgift
ORDER BY codes.pickedgift
You should use a sub-select for this query.
-- assuming I have your table structure correct.
SELECT p.productno, p.productname, num
FROM (SELECT codes.pickedgift, COUNT(codes.pickedgift) as num
FROM codes
GROUP BY codes.pickedgift) g
JOIN products p ON p.id = g.pickedgift
ORDER BY g.pickedgift
The other thing you have to make sure of is if you're using a group-by, the fields in your select must either be the fields in the group by, or aggregates. MySQL let's you include columns that are not part of the group-by / aggregate, it becomes ambiguous as to which value productno and productname should be represented, which is why I opted for a sub-select instead.

Return two identical rows in MySQL

I have an ordering system that can have multiple receipts related to one order. I recently ran into a query as follows that produced an undesirable result.
SELECT info FROM orders WHERE id IN (1, 2, 2) ORDER BY FIELD (id, 1, 2, 2);
Is there a way to return the row for order #2 twice? As of right now the query returns row one then row two as expected; however, in this particular instance returning row #2 twice is needed.
The tables are roughly as follows (I know it isnt totally valid MySQL, just for illustration):
CREATE TABLE orders (
id int(),
info VARCHAR(),
)
CREATE TABLE links (
orderid int(),
receiptid int()
)
CREATE TABLE receipts (
id int(),
otherinfo VARCHAR(),
)
If I'm understanding the situation correctly, you have two entries in the orders table
but orderId 2 is listed twice in the links table. If that is correct, then what you want is:
select o.info from orders o
inner join links l on o.id = l.orderid
If you need to return the row twice, then filtering in the where clause is not what you want. You can do this by filtering using a join:
SELECT o.info
FROM orders o join
(select 1 as id union all select 2 union all select 2
) ids
on o.id = ids.id
ORDER BY FIELD (o.id, 1, 2, 2);
Well, you coul make use of a UNION ALL
Something like
SELECT info FROM orders WHERE id IN (1, 2)
UNION ALL
SELECT info FROM orders WHERE id IN (2)