Combine 3 tables with sum mysql - mysql

I have a problem with my query. I've managed to display data from 2 tables. Next I want to add up SALE_AMT from the 3rd table, the problem is that order by cannot, the program output adds up all data not by order by
This my query:
SELECT
customer.CUST_NO, customer.CUST_NM,
store.STR_CD, store.STR_NM, SUM(SALE_AMT)
FROM
customer, store, cust_sale_pnt
GROUP BY
CUST_NO
table customer
table cust_sale_pnt
table store
My result
my result
Can you guys help me to sum data based on grouping cust_no?

The problem is, that you don't specify a condition that's used to combine the records of the different tables. In effect, you're creating a 'cross join'.
That is, any record of table customer is combined with any record of table store and the result is combined with any record of table cust_sale_pnt.
In effect, you get each of your 3 customers combined with each of your 6 sales. Therefore the sum over sale_amt is identical for each customer.
You want an INNER JOIN to combine the records:
SELECT c.CUST_NO, c.CUST_NM, SUM(csp.SALE_AMT)
FROM customer c
INNER JOIN cust_sale_pnt csp ON c.CUST_NO = csp.CUST_NO
INNER JOIN store ON csp.STR_CD = store.STR_CD
GROUP BY c.CUST_NO, c.CUST_NM;

Related

Join more than two tables

I am trying to join 2 tables and in 1 table there may or may not have the corresponding values.but i need to join the table and list the fields as null.
I have tried to join the tables as left join.but If two entries is there in secoond table corresponding to the value of first table,then first table data is displayed twice.
I need to display only one time if there is two data in another table or there is no data in another table,but it should display as null.
Here is my sql query.
SELECT *,incident.incident_id as incidentid
FROM register_incident AS incident
LEFT JOIN incident_images AS im ON im.incident_id=
incident.incident_id
WHERE incident.state='Active'
I need to display only one time each data if there is no corresponding rows in another table,but the fields in the second table list as null.
If there is more than one row in another table,then also display each row in first table one time with one entry in the second table.
you can use select distinct for get only one row eg (limiting the select to indicent_id ,, but you can add the distinctcolumn you need ):
SELECT *,incident.incident_id as incidentid
FROM register_incident AS incident
LEFT JOIN (
select distinct incident_id from
incident_images
WHERE incident.state='Active' ) t ON t.incident_id= incident.incident_id

SQL: How to build complex query from 3 tables

I have 3 tables with data and I need to select sum of sales (SalesAmount) per country(CountryRegionName) in 2014 fiscal year (FiscalYear).
The first table is Geography.
There are data with CountryRegionName and also SalesTerritoryKey (number which means some districts of CountryRegionName).
The second table, anong others, has information about OrderDateKey, SalesTerritoryKey and SalesAmount. The OrderDateKey field include records in the following format: "20130828".
The third table, among others, has fields DateKey (in the same format as OrderDateKey from second table and FiscalYear (format like: "2012").
I dont't understand how I can select needed data using all 3 tables because second table has information about year (OrderDateKey) in different format which third table supports in field FiscalYear.
Currently I stopped which following statement:
`SELECT CountryRegionName, SUM(SalesAmount) FROM FirstTable GROUP BY SalesTerritoryKey`
I know that we need to join all tables and make some subqueries but don't understand how to compare dates and countries which are in different formats.
Thanks for your help!
SELECT t1.CountryRegionName, SUM(t2.SalesAmount)
FROM ThirdTable t3
LEFT JOIN SecondTable t2
ON t3.DateKey = t2.OrderDateKey
LEFT JOIN FirstTable t1
ON t1.SalesTerritoryKey = t2.SalesTerritoryKey
WHERE t3.FiscalYear = "2014"
GROUP BY t1.CountryRegionName

Finding Sum of values of a particular group in Table

I have two tables in MySQL. The first one is Catalog with one of its columns as Category, and another table Stock with SP and CP as columns. I want to find the total profit of each category.
I am not able to come up with an appropriate query. Every query I try gives an error. Can anyone help?
select A.Category,sum(B.SP group by A.Category) as TotalSP,sum(B.CP group by A.Category) as TotalCP,
case
when TotalSP>TotalCP then ((TotalSP-TotalCP)/TotalSP)*100
when TotalSP<TotalCP then ((TotalSP-TotalCP)/TotalCP)*100
end
as TotalProfit
from Catalog A,Stock B;
Note: negative profit automatically considered as loss.
select A.Category,sum(B.SP) as TotalSP,sum(B.CP) as TotalCP,
case
when TotalSP>TotalCP then ((TotalSP-TotalCP)/TotalSP)*100
when TotalSP<TotalCP then ((TotalSP-TotalCP)/TotalCP)*100
end
as TotalProfit
from Catalog A
INNER JOIN Stock B ON B.catalog_id = A.id/*Write how your tables linked here*/
group by A.Category;
This query selects all catalog records, joins stock data to it, then groups results by category, counts sums in each group.

How to store SQL Query result in table column

I'm aware of the INSERT INTO table_name QUERY; however, I'm unsure how to go about achieving the desired result in this case.
Here's a slightly contrived example to explain what I'm looking for, but I'm afraid I cannot put it more succiently.
I have two tables in a database designed for a hotel.
BOOKING and CUSTOMER_BOOKING
Where BOOKING contains PK_room_number, room_type, etc. and CUSTOMER_BOOKING contains FK_room_number, FK_cusomer_id
CUSTOMER_BOOKING is a linking table (many customers can make many bookings, and many bookings can consist of many customers).
Ultimately, in the application back-end I want to be able to list all rooms that have less than 3 customers associated with them. I could execute this a separate query and save the result in the server-side scripting.
However, a more elegant solution (from my point of view) is to store this within the BOOKING table itself. That is to add a column no_of_bookings that counts the number of times the current PK_room_number appears as the foreign key FK_room_number within the CUSTOMER_BOOKING table. And why do this instead? Because it would be impossible for me to write a single complicated query which will both include the information from all ROOMS, among other tables, and also count the occurrences of bookings, without excluding ROOMS that don't have any bookings. A very bad thing for a hotel website attempting to show free rooms!
So it would look like this
BOOKING: PK_room_number (104B) room_type (double) room_price (high), no_of_bookings (3)
BOOKING: PK_room_number (108C) room_type (single) room_price (low), no_of_bookings (1)
CUSTOMER_BOOKING: FK_room_number (104B) FK_customer_id (4312)
CUSTOMER_BOOKING: FK_room_number (104B) FK_customer_id (6372)
CUSTOMER_BOOKING: FK_room_number (104B) FK_customer_id (1112)
CUSTOMER_BOOKING: FK_room_number (108C) FK_customer_id (9181)
How would I go about creating this?
Because it would be impossible for me to write a single complicated
query which will both include the information from all ROOMS, among
other tables, and also count the occurrences of bookings, without
excluding ROOMS that don't have any bookings.
I wouldn't say it's impossible and unless you're running into performance issues, it's easier to implement than adding a new summary column:
select b.*, count(cb.room_number)
from bookings b
left join customer_booking cb on b.room_number = cb.room_number
group by b.room_number
Depending on your query may need to use a derived table containing the booking counts for each room instead instead
select b.*, coalesce(t1.number_of_bookings,0) number_of_bookings
from bookings b
left join (
select room_number, count(*) number_of_bookings
from customer_booking
group by room_number
) t1 on t1.room_number = b.room_number
You have to left join the derived table and select coalesce(t1.number_of_bookings,0) in case a room does not have any entries in the derived table (i.e. 0 bookings).
A summary column is a good idea when you're running into performance issues with counting the # of bookings each time. In that case I recommend creating insert and delete triggers on the customer_booking table that either increment or decrement the number_of_bookings column.
You could do it in a single straight select like this:
select DISTINCT
b1.room_pk,
c1.no_of_bookings
from cust_bookings b1,
(select room_pk, count(1) as no_of_bookings
from cust_bookings
group by room_pk) c1
where b1.room_pk = c1.room_pk
having c1.no_of_bookings < 3
Sorry i used my own table names to test it but you should figure it out easily enough. Also, the "having" line is only there to limit the rows returned to rooms with less than 3 bookings. If you remove that line you will get everything and could use the same sql to update a column on the bookings table if you still want to go that route.
Consider below solutions.
A simple aggregate query to count the customers per each booking:
SELECT b.PK_room_number, Count(c.FK_customer_id)
FROM Booking b
INNER JOIN Customer_Booking c ON b.PK_room_number = c.FK_room_number
GROUP BY b.PK_room_number
HAVING Count(c.FK_customer_id) < 3; # ADD 3 ROOM MAX FILTER
And if you intend to use a new column no_of_booking, here is an update query (using aggregate subquery) to run right after inserting new value from web frontend:
UPDATE Booking b
INNER JOIN
(SELECT b.PK_room_number, Count(c.FK_customer_id) As customercount
FROM Booking b
INNER JOIN Customer_Booking c ON b.PK_room_number = c.FK_room_number
GROUP BY b.PK_room_number) As r
ON b.PK_room_number = r.PK_room_number
SET b.no_of_booking = r.customercount;
the following generates a list showing all of the bookings and a flag of 0 or 1 if the the room has a customer for each of the rooms. it will display some rooms multiple times if there are multiple customers.
select BOOKING.*,
case CUSTOMER_BOOKING.FK_ROOM_NUMBER is null THEN 0 ELSE 1 END AS BOOKING_FLAG
from BOOKING LEFT OUTER JOIN CUSTOMER_BOOKING
ON BOOKING.PK_room_numer = CUSTOMER_BOOKING.FK_room_number
summing and grouping we arrive at:
select BOOKING.*,
SUM(case when CUSTOMER_BOOKING.FK_ROOM_NUMBER is null THEN 0 ELSE 1 END) AS BOOKING_COUNT
from BOOKING LEFT OUTER JOIN CUSTOMER_BOOKING
ON BOOKING.PK_room_number = CUSTOMER_BOOKING.FK_room_number
GROUP BY BOOKING.PK_room_number
there are at least two other solutions I can think of off the top of my head...

Invalid results returning from a multi-table SELECT Statement

I have a Database with the following structure:
http://i.imgur.com/DFZz3Py.png
I'm trying to run a select statement, getting information from multiple tables, however it keeps bringing me duplicate results. The statement I'm using is:
SELECT StockReceipts.StockID, StockReceipts.Quantity, StockPriceHistory.Price
FROM StockReceipts,StockPriceHistory,Receipts
WHERE (Receipts.ReceiptID = 1) AND (Receipts.OrderDate BETWEEN StockPriceHistory.DateStart AND StockPriceHistory.DateEnd)
And the results i'm getting are:
http://i.imgur.com/2ZrgYyZ.png
What I actually want is matching rows from the stockreceipts table,
but with the price for each item of stock (the price that was within the date & time of ordering - OrderDate taken from the Receipts table) as well, taken from the StockPriceHistory table. I don't understand why it's making up duplicate/incorrect rows when there are only two rows in the StockReceipts table for that receipt.
Can anyone help? Thanks
SELECT
SR.StockID,
SR.Quantity,
SPH.Price
FROM
Receipts R
JOIN StockReceipts SR
on R.ReceiptID = SR.ReceiptID
JOIN StockPriceHistory SPH
on SR.StockID = SPH.StockID
WHERE
R.ReceiptID = 1
AND R.OrderDate BETWEEN SPH.DateStart AND SPH.DateEnd
You had no JOIN conditions between the tables leaving it a Cartesian result... For every record in one, grabbed entries from all other table rows.