So I have a 2 tables inside of the database. The first is just a unique ID to name mapping
Customers
UID | CustomerName
In a second table I have something like the following
Orders
OrderNum | CustomerID | CustomerID2
Now I would like to insert into orders, but I only have the name of the 2 customer names, so I'm imagining something like the following (which doesnt work)
insert into Orders select null, UID as id1, UID as id2 from Customers where CustomerName=="sven";
How can I go about getting the two UID's from the first table?
Also I need to be able to do the reverse and select from the table
SELECT * FROM Orders a JOIN (Customers b) ON a.UID=b.UID WHERE b.CustomerName='sven'
Neither of these work, and I can't seem to find something similar online strangely.
UPDATE: Based on your comments if you're trying to insert two different customers' ids to one order you can do
INSERT INTO Orders (CustomerID, CustomerID2)
SELECT c1.uid uid1, c2.uid uid2
FROM
(
SELECT uid
FROM customers
WHERE customername = 'sven'
LIMIT 1
) c1 CROSS JOIN
(
SELECT uid
FROM customers
WHERE customername = 'jhon'
LIMIT 1
) c2
To select an order where one of the customers exists
SELECT o.*
FROM orders o LEFT JOIN customers c1
ON o.customerid = c1.uid LEFT JOIN customers c2
ON o.customerid2 = c2.uid
WHERE c1.customername IN('sven', 'jhon')
OR c2.customername IN('sven', 'jhon')
Here is SQLFiddle demo
Original answer: Are you looking for this?
To insert
INSERT INTO Orders (CustomerID, CustomerID2)
SELECT c1.uid uid1, c2.uid uid2
FROM customers c1 LEFT JOIN customers c2
ON c1.customername = c2.customername
AND c1.uid < c2.uid
WHERE c1.customername = 'sven'
LIMIT 1
To select
SELECT o.*
FROM orders o LEFT JOIN customers c1
ON o.customerid = c1.uid LEFT JOIN customers c2
ON o.customerid2 = c2.uid
WHERE c1.customername = 'sven'
OR c2.customername = 'sven'
Here is SQLFiddle demo
To insert into one table from another table use this syntax:
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
So in your case your query should be:
INSERT INTO Orders (CustomerID, CustomerID2)
SELECT UID, UID
FROM Customers WHERE CustomerName = 'sven';
If you want to insert multiple record from a single query you can use IN operator instead of = like this:
INSERT INTO Orders (CustomerID, CustomerID2)
SELECT UID, UID
FROM Customers WHERE CustomerName IN ('sven', 'smith');
There is a mistake in your join in the SELECT query:
You joined both tables with UID while there is no UID in Orders table. May be you mean CustomerID. Try this one:
SELECT * FROM Orders a
JOIN Customers b
ON a.CustomerID = b.UID
WHERE b.CustomerName='sven'
See this SQLFiddle
Related
CUSTOMERS
NAME
ID
ORDERS
CID
ITEMS
New customer orders in orders table have new data record like:
CID 134 - CAR
CID 135 - PHONE
CID 134 - TEA
I need to select only customers that have 1 record in the orders table, in dat above its CID 135
IDN=CID
I need to select IDN that have only one ITEMS record, I tried:
SELECT customers.name, orders.items
FROM customers JOIN orders
WHERE Items > 2
but doesn't work :(
You just need to modify your where clause. This query will return only customers that have exactly one row in the orders table.
SELECT customers.name,
orders.items
FROM customers
LEFT JOIN orders
on customers.ID = orders.CID
WHERE customers.ID IN (SELECT CID from orders GROUP BY CID HAVING COUNT(*) = 1)
Try adding an ON statement for your join. This tells SQL how to connect the two tables.
SELECT
customers.name
, orders.items
FROM customers
JOIN orders
on customers.ID = orders.CID
WHERE Items > 2
You must add a another subquery which count the numbers,
CREATE tABLE customers (ID int, name varchar(10))
INSERT INTO customers VALUES (1,'A'),(2,'b')
CREATE tABLE orders (ID int,CID int,items varchar(10))
INSERT INTO orders VALUES (1,1,'car'),(2,1,'car2'),(3,2,'car'),(4,2,'car2'),(5,2,'car2')
SELECT
customers.name
, orders.items
FROM customers
JOIN orders
on customers.ID = orders.CID
INNER JOIN (SELECT COUNT(*) countr,CID FROM orders GROUP BY CID) o1 on o1.CID = orders.CID
WHERE countr > 2
name | items
:--- | :----
b | car
b | car2
b | car2
db<>fiddle here
You can do:
select * from customers
where id in (
select cid from orders group by cid having count(*) = 1
)
I have a query with WHERE EXISTS and DISTINCT. I just want to find distinct emails with same order_id
How can I make this faster
select DISTINCT(user_email)
from (
SELECT *
FROM orders mto
WHERE EXISTS
(
SELECT 1
FROM orders mti
WHERE mti.order_id = mto.order_id
LIMIT 1, 1
)
) as z
INNER JOIN marketplaces as u ON z.ump_id = u.id
You are doing excess/needless work - the EXISTS will always return TRUE in your situation.
If you want a list of all (unique) emails which have at least 1 order, then
SELECT
user_email
FROM
marketplaces
LEFT JOIN
orders ON ump_id = marketplaces.id
WHERE orders.id IS NOT NULL
GROUP BY user_email
If you want to get a list with all (unique) emails for a given order ID, then
SELECT
user_email
FROM
orders
LEFT JOIN
orders ON ump_id = marketplaces.id
WHERE orders.id = 17
GROUP BY user_email
I have 2 tables in my database.
table customer with ID,firstName,lastName,address...
and table orders with id, idCustomer...
and I want to delete all the orders of the customers where the first name is "john"
How I write the command?
thanks
DELETE o
FROM Orders o
INNER JOIN Customer c ON o.idCustomer = c.ID
WHERE c.firstName = 'john'
Delete From
orders
Where
Orders.firstName In
(Select
firstName
From
customers
Inner Join orders On customers.ID = orders.idCustomer
Where
customers.firstName = "john")
I'm fairly new to more advanced SQL queries
Given the following tables and associated fields:
Person
PersonId, FirstName, LastName
Order
OrderId, PersonId, OrderDateTime
I want to write a query that will join both tables by PersonId and will retrieve every person and their most recent order.
So if James Doe (PersonId = 1) below has many orders in the orders table,
OrderId, PersonId, OrderDateTime
1 1 12/1/2013 9:01 AM
2 1 2/1/2011 5:01 AM
3 2 10/1/2010 1:10 AM
it will only take the most recent for his.
PersonId NameFirst NameLast OrderId OrderDateTime
1 James Doe 1 12/1/2013 9:01 AM
2 John Doe 3 10/1/2010 1:10 AM
I have been trying something like this
SELECT p.PersonID, o.OrderID, MAX(o.OrderDateTime) From Person p
JOIN Orders o ON p.PersonID = o.PersonID
GROUP BY p.PersonID,
Thanks
The inner query in this solution is a temporary table containing the most recent orders for each person. I join this back to the Orders table to get the fields you want, and then join again to the Person table.
SELECT p.PersonID, p.NameFirst, p.NameLast, o.OrderID, o.OrderDateTime
FROM Person p INNER JOIN Orders o
ON o.PersonId = p.PersonId
INNER JOIN
(
SELECT o1.PersonId, MAX(o1.OrderDateTime) AS maxTime
FROM Orders o1
GROUP BY o1.PersonId
) t
ON o.PersonId = t.PersonId AND o.OrderDateTime = t.maxTime
You can use variables to simulate ROW_NUMBER not available in MySQL:
SELECT p.PersonId, FirstName, LastName,
o.OrderId, o.OrderDateTime
FROM Person AS p
LEFT JOIN (
SELECT OrderId, OrderDateTime, PersonId,
#row_number := IF(#pid <> PersonId,
IF(#pid:=PersonId, 1, 1),
IF(#pid:=PersonId, #row_number+1, #row_number+1)) AS rn
FROM `Order`
CROSS JOIN (SELECT #row_number := 0, #pid := 0) vars
ORDER BY OrderDateTime DESC
) AS o ON p.PersonId = o.PersonId AND o.rn = 1
rn = 1 for the top level record within each PersonId slice of the derived table. Using this predicate in the ON clause of the LEFT JOIN we can match each row of Person to the most recent row of Order and obtain all Order fields.
Demo here
EDIT:
In SQL-Server the query looks like this:
SELECT p.*, o.OrderId, o.OrderDateTime
FROM Person AS p
LEFT JOIN (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY PersonId
ORDER BY OrderDateTime DESC) AS rn
FROM [Order]
) AS o ON p.PersonId = o.PersonId AND o.rn = 1
So the most recent order per every person. You could do something like this:
select p.*, o.*
from person p
inner join orders o on p.personId = o.personId
inner join (
-- get the max order per person
SELECT max(orderId) as orderId, personId
from orders
group by personId
) maxOrder on o.orderId = maxOrder.orderId
joining o onto maxOrder on the orderId filters the result set only to the orders that are also the maximum order per customer.
Note that I used the ID on the table rather than the datetime, as the ID is guaranteed to be unique (for help with joins) - this is not always available depending on the nature of the use in the table, but it looks like it should work for your case.
I have troubles getting proper data.
I have table structure like:
id INT(11) AI
order_id INT(11)
status varchar(45)
This table log status changes for orders.
So order_id's will have few statuses.
Now I need to select rows and group them by order_id, where order never had status (not even one status with given order_id) != 'example'
We don't show orders, where one of members had status = example
Sample data
1 12 ready
1 12 example
2 13 ready
2 13 sent
So I don't want order 12 to show at all, because one of it members have "example" status
I've tried grouping results, but it's not enough.
you can do it by simple join query :
select a.order_id
from ordrstatus as a left outer join (select orderid , count(*) as status from orderstatus where status = 'example' group by orderid) as b on a.orderid = b.orderid
where b.status = 0 or b.status is NUll
Join query always run faster then IN query . by using Join in query it will run only one time .
You can try like this...it will return all order id which never had status -example
Select
Order_id,
from TableName A where Not Exists(
Select id from TableName B where
status='example' and
a.Order_id=b.Order_id
)
group by Order_id
Not quite sure if you want the records for order which have had a status of example, or ones which have never had a status of example
To get a list of orders (with the status grouped up) which have had a status of example:-
SELECT a.order_id, GROUP_CONCAT(a.status)
FROM SomeTable a
INNER JOIN
(
SELECT order_id, COUNT(*)
FROM SomeTable
WHERE status = 'example'
GROUP BY order_id
) b
ON a.order_id = b.order_id
GROUP BY order_id
To get those which have NEVER had a status of exmaple
SELECT a.order_id, GROUP_CONCAT(a.status)
FROM SomeTable a
LEFT OUTER JOIN
(
SELECT order_id, COUNT(*)
FROM SomeTable
WHERE status = 'example'
GROUP BY order_id
) b
ON a.order_id = b.order_id
WHERE b.order_id IS NULL
GROUP BY order_id
EDIT
SELECT a.order_id, GROUP_CONCAT(a.status)
FROM SomeTable a -- Statuses
LEFT OUTER JOIN
(
SELECT order_id, COUNT(*)
FROM SomeTable
WHERE status = 'example'
GROUP BY order_id
) b -- Get any order id which has had a status of example (as a LEFT JOIN)
ON a.order_id = b.order_id
INNER JOIN
(
SELECT order_id, MAX(id) AS Latestid
FROM SomeTable
GROUP BY order_id
) c -- Get the latest status for each order (ie, max id)
ON a.order_id = c.order_id
LEFT OUTER JOIN
(
SELECT order_id, id
FROM SomeTable
WHERE status = 'example2'
) d -- Get the id of the order status of example2
ON a.order_id = d.order_id AND c.Latestid = d.id -- join on the same order id and that the record id matches the latest record id
WHERE b.order_id IS NULL -- reject those where a match was found on example for any status
AND d.order_id IS NULL -- reject those where a match was found on example2 for the latest status
GROUP BY order_id
try this
SELECT Order_ID FROM tbl_Orders
WHERE Status NOT IN ('example')
GROUP BY Order_ID
SELECT DISTINCT x.order_id
FROM order_status x
LEFT
JOIN order_status y
ON y.order_id = x.order_id
AND y.status = 'example'
WHERE y.id IS NULL;