mysql join two different tables to list one result - mysql

I have two MySQL tables: 'invoice' and 'credit_memo'
I would like to combine them and list one result ordered by date.
invoice:
ID INT
date DATETIME
customer_id INT
credit_memo:
ID INT
date DATETIME
customer_id INT
My final attempt:
(SELECT ID AS invoice_number FROM invoice)
UNION
(SELECT ID AS credit_memo_number FROM credit_memo)
ORDER BY date
The problem is that both the invoice_number and credit_memo_number get put into the invoice_number variable. So when I run the result it all looks like its coming from the 'invoice' table.
How can I determine which table each particular row is pulling from?
Thank you,
Andy

Here is how you will approach it.
Both tables have customer ID so we can join them through that:
SELECT i.ID AS invoice_number,c.ID AS credit_memo_number
FROM invoice i
JOIN credit_memo c ON c.customer_id = i.customer_id
ORDER BY i.date ASC
This will select the invoice ID and the credit ID and order them by the Invoice date.

select id, t.table_name from invoice join information_schema.tables t on t.table_name='invoice'
union
select id, t.table_name from credit_memo join information_schema.tables t on t.table_name='credit_memo'

Related

How to match up dates on 2 different tables and join to an ID table?

I have a table full of product ids and their attributes. I want to join sales data and receipt data from 2 different tables and a different row for each id and date combo. So I want the output to look like this:
I tried joining the product id table and sales table to the receipt table but I'm not sure how to get the dates from the sales and receipts table to match up. Not sure of how to approach this. Thanks!
Calculate the counts for each table and combine them usung UNION ALL
select
product_id
,sales_date
-- combine the counts from both tables
,sum(sales_count)
,sum(receipt_count)
from
(
-- get the counts for the sales table
select
product_id
,sales_date
,count(*) as sales_count
-- UNION needs the same number of columns in both Select -> adding a dummy column
-- 1st Select determines the datatype
,cast(0 as int) as receipt_count
from sales
group by product_id, sales_date
UNION ALL
-- get the counts for the receipts table
select
product_id
,receipt_date
,0
,count(*)
from receipts
group by product_id, receipt_date
) as dt
group by product_id, receipt_date
select p.product_id, s.sales_date, s.sales_count, r.receipt_count
from
products p,
(select count(*) sales_count, sales_date, product_id from sales group by 2,3) s
(select count(*) receipt_count, receipt_date, product_id from receipts group by 2,3) r
where
p.product_id = s.product_id
and p.product_id = r.product_id
and s.sales_date=r.receipt_date
;

Get the max column value for each unique ID

I have two tables, a customers and orders table.
The customers table contains a unique ID for each customer. It contains 1141 entries.
The orders table contains many entries with a customerID and a date.
I am trying to query my database and return a list of customers and the max(date) from the orders list.
SELECT *
FROM customers
INNER JOIN
(
SELECT CustomerID, max(date) as date
FROM orders
GROUP BY CustomerID
) Sub1
ON customers.id = Sub1.CustomerID
INNER JOIN orders
ON orders.CustomerID = Sub1.CustomerID
AND orders.date = Sub1.Date
However this query is returning 1726 rows instead of 1141 rows. Where is this getting extra from?
I think it's beacause ORDERS table contains same customerID multiple times, so when you join the table with CUSTOMERS, each CUSTOMER.id matches multiple rows of ORDERS.
The problem is that there are ties.
For a given customer, some place more than one order per day. So there's a possibility that occasionally some may have placed more than one order on the date that is their max date.
To fix this, you need to use MAX() or some column that is always unique in the Orders table (or at least unique within a given date). This is easy if you can depend on an auto-increment primary key in the Orders table:
SELECT *
FROM customers
INNER JOIN
(
SELECT CustomerID, max(orderid) as orderid as date
FROM orders
GROUP BY CustomerID
) Sub1
ON customers.id = Sub1.CustomerID
INNER JOIN orders
ON orders.CustomerID = Sub1.CustomerID
AND orders.orderid = Sub1.orderid
This assumes that orderid increases in lock-step with increasing dates. That is, you'll never have an order with a greater auto-inc id but an earlier date. That might happen if you allow data to be entered out of chronological order, e.g. back-dating orders.
;with cte as
(
select CustomerID, orderdate
, rn = row_number() over (partition by customerID order by orderdate desc)
from orders
)
select c.*, cte.orderdate
from customer c
join cte on cte.customerID = c.customerid
where rn =1 -- This will limit to latest orderdate

MySQL - Return the last record on the second table then return all in the first table

I have two tables customers and orders, below is the structure.
Table - contacts
id
Table - orders
id
contact_id
How can I select all from contacts table but only select the latest record from the orders table?
SELECT contacts.*,
Max(orders.id)
FROM contacts
LEFT JOIN orders
ON contacts.id = orders.contact_id
GROUP BY contacts.id;
But I always gets NULL if I use LEFT JOIN, it only have value if I use INNER JOIN.
select the latest record in orders and group it first
select contacts.*, orders.id
from contacts
left join (select max(id) as id, contact_id
from orders
group by contact_id) orders
on contacts.id = orders.contact_id
You can try to use UNION like
select * from orders order by id desc limit 1
UNION
select * from contacts
In order to aggregate max value with all columns from contacts table, add all columns from contacts table after group by function
I trust the answer provided by Alex should work well. The following query shall list all records from contacts and the last id from orders table.
SELECT
c.*,
(SELECT Max(o.id) FROM orders o
INNER JOIN contacts c1 ON o.id=c1.id
)as last_order_id
FROM contacts c

Single query instead of multiple select statements

Hello I am stuck in a SQL statement situation. Can anyone help me with the statement:
Table 1.
Customers
customer_id | customer_name | custom_url | customer_desc
Table 2.
Categories
category_id | customer_id | category_name
select customer_id where category_name="Realtor";
gives me a list of customer ids. Now I use them to find all their names, desc and url from the customers table.
I need to do this in a single query and process the customer details to display on the UX. I am really stuck how to do this.
Here is what i have (which I know is wrong)
select * from customers where customer_id = Loop (select customer_id from categories where category_name="Realtor");
Modify your query to a JOIN query like
select c.*
from customers c
join categories ca on c.customer_id = ca.customer_id
where ca.category_name='Realtor';
You can do what you want using IN or ANY or EXISTS:
select *
from customers
where customer_id = ANY (select customer_id
from categories
where category_name = 'Realtor'
);
Or:
select *
from customers
where customer_id IN (select customer_id
from categories
where category_name = 'Realtor'
);

SQL query to return data from multiple tables?

I have tables with the following schemas:
items (itemID: integer, description: string, price: integer)
orders (orderID: integer, itemID: integer, aID: integer, customerID: integer, date: date)
I would like to find out each item for which there is only one order, return the itemID, description, and the date of the order.
I have the following code so far:
SELECT *
FROM (
SELECT *
FROM orders
GROUP BY itemID
HAVING COUNT(*) = 1
) AS ONLY_ONCE
But this returns only the information from the orders table (orderID, itemID, aID, and customerID)
in my code I search for items for which the itemID appears only once in the orders table, which means that it was only ordered once.
How do I get the description of these items which is in the items table?
I tried using the join function to do this but was not successful.
Thanks
You were very close... try this:
SELECT *
FROM items
WHERE itemID IN (
SELECT itemID
FROM orders
GROUP BY itemID
HAVING COUNT(*) = 1
)
If you also want the date from orders in your result set, there are many ways to do that, but I'd opt for a CTE and an inner join over the IN operator, like so:
;WITH SingleOrders AS (
SELECT itemID, MAX([date]) AS [Date]
FROM orders
GROUP BY itemID
HAVING COUNT(*) = 1
) SELECT *
FROM items i
INNER JOIN SingleOrders so ON i.itemID = so.itemID
The first part declares a common table expression called "SingleOrders" which consists of two columns: the ID and the Date for each itemID that has only one order. The MAX(date) returns the one and only date, and is required because of the GROUP BY clause.
The actual SELECT statement then joins this CTE with the items table to select out only the itemIDs that have just one order, and since it includes all the columns from both the items and the SingleOrders tables, will include the date.
If you don't want to use a CTE (or can't use one), something like this might work for you... just add an inner join back to the orders table to pick up the date:
SELECT i.*, o.date
FROM items i
INNER JOIN orders o ON i.itemID = o.itemID
WHERE i.itemID IN (
SELECT itemID
FROM orders
GROUP BY itemID
HAVING COUNT(*) = 1
)
You need to join your 'group' table result with the original data
SELECT I.*
FROM items I
INNER JOIN(
SELECT itemID
FROM orders
GROUP BY itemID HAVING COUNT(1)=1
) O ON O.itemID=I.itemID