How can I select multiple records from more that two tables - sql

I am a complete beginner in SQL and need some help to learn. I have this learning material I found online and trying to write queries per the instructions. I did the first but got stuck on the rest of the queries. Can anyone please help me write any one of the queries below?
[]
Please help me learn how to do the rest.
b) Get aids and names of agents who have placed individual orders of at least $500 for any customer living
in Kyoto.
c) What cities do those customers live in, who enjoy discount under 10% and have ordered at least 1000
combs so far (in all their orders put together)?
d) What product names have been ordered by at least one customer based in Dallas through any agent based
in Tokyo?
e) Get the name, city, and total dollar amount of all orders placed by each customer, arranged in descending
order of the amounts.
Here is how I managed to do the first one.
a) Get pairs of all customer cids and agent aids, who live in the same city.
SELECT customer.cid, agent.aid FROM customers, agent WHERE customer.city = agent.city
RESULT
cid
aid
c001
a05
c004
a05
c002
a06
c003
a06

Try this one for b
SELECT distinct Agents.City -- Distinct becuase you dont want more then one of the same city being returned
FROM Agents
JOIN Orders
ON orders.aid = agents.aid
WHERE orders.cid = 'c002' -- Checks the orders table for any cid equal to c002

Related

Query that will identify rows that should be identical (Except with 2 exceptions)

we have a customer table and some customers appear multiple times if they are available for multiple offices. If someone adds a customer multiple times, I want to be able to run a report to see if they have done it correctly for each location, but I don't really have a clue where to start. Here is an example
UID, Office, CustomerCode, CUSTOMERNAME, CUSTOMERHEADOFFICEPHONE
001, Manchester, 123, 123 Supplied Ltd, 0161 123456
002, London, 123, 123 Suppls Ltd, 0161 123446
So we can sell stuff to customer '123' from both our Manchester and London offices. The report should focus on the CustomerCode and make sure whenever '123' appears all the CAPITAL rows should be the same with the exception of UID (Always different), Office (Naturally that is different). So the report would see that not all the CustomerNames are identical and they have also made a mistake on the CustomerHeadOfficePhone. If I had thousands of rows and all the other 'multi-customers' matched up, I'd want my report to just show these 2 rows. How would I go about that please?
I would try:
select CustomerCode, CustomerName, CustomerHeadOfficePhone, count(*)
from TableName
group by CustomerCode, CustomerName, CustomerHeadOfficePhone
having count(*) > 1
That will list every occurrence of the records with different values, which you would need if you were going to delete them. You could shorten the list by using DISTINCT, and you could present the UIDs in a better way with an additional query around this one. But it seems that you have only asked for the list of things to fix, and I believe this will give it to you.

SQL-sum over dynamic period

I have 2 tables: Customers and Actions, where each customer has uniqe ID (which can be found in each table).
Part of the customers became club members at a specific date (change between the customers). I'm trying to summarize their purchases until that date, and to get those who purchase more than (for example) 200 until they become club members.
For example, I can have the following customer:
custID purchDate purchAmount
1 2015-05-12 100
1 2015-07-12 150
1 2015-12-29 320
Now, assume that custID=1 became a club member at 2015-12-25; in that case, I'd like to get SUM(purchAmount)=250 (pay attention that I'd like to get this customer because 250>200).
I tried the following:
SELECT cust.custID, SUM(purchAmount)totAmount
FROM customers cust
JOIN actions act
ON cust.custID=act.custID
WHERE act.clubMember=1
AND cust.purchDate<act.clubMemberDate
GROUP BY cust.custID
HAVING totAmount>200;
Is it the right way to "attack" this question, or should I use something like while loop over the clubMemberDate (which telling the truth-I don't know how to do)?
I'm working with Teradata.
Your help will be appreciated.

POSTGRESQL - Finding specific product when

I've attempted to write a query but I've not managed to get it working correctly.
I'm attempting to retrieve where a specific product has been bought but where it also has been bought with other products. In the case below, I want to find where product A01 has been bought but also when it was bought with other products.
Data (extracted from tables for illustration):
Order | Product
123456 | A01
123457 | A01
123457 | B02
123458 | C03
123459 | A01
123459 | C03
Query which will return all orders with product A01 without showing other products:
SELECT
O.NUMBER
O.DATE
P.NUMBER
FROM
ORDERS O
JOIN PRODUCTS P on P.ID = O.ID
WHERE
P.NUMBER = 'A01'
I've tried to create a sub query which brings back just orders of product A01 but I don't know how to place it in the query for it to return all orders containing product A01 as well as any other product ordered with it.
Any help on this would be very grateful.
Thanks in advance.
You can use conditional SUM to detect if one ORDER group have one ore more 'A01'
CREATE TABLE orders
("Order" int, "Product" varchar(3))
;
INSERT INTO orders
("Order", "Product")
VALUES
(123456, 'A01'),
(123457, 'A01'),
(123457, 'B02'),
(123458, 'C03'),
(123459, 'A01'),
(123459, 'C03')
;
SELECT "Order"
FROM orders
GROUP BY "Order"
HAVING SUM(CASE WHEN "Product" = 'A01' THEN 1 ELSE 0 END) > 0
I appreciated Juan's including the DDL to create the database on my system. By the time I saw it, I'd already done all the same work, except that I got around the reserved word problem by naming that field Order1.
Sadly, I didn't consider that either of the offered queries worked on my system. I used MySQL.
The first one returned the A01 lines of the two orders on which other products were ordered too. I took Alex's purpose to include seeing all items of all orders that included A01. (Perhaps he wants to tell future customers what other products other customers have ordered with A01, and generate sales that way.)
The second one returned the three A01 lines.
Maybe Alex wants:
select *
from orders
where Order1 in (select Order1
from orders
where Product = 'A01')
It outputs all lines of all orders that include A01. The subquery makes a list of all orders with A01. The first query returns all lines of those orders.
In a big database, you might not want to run two queries, but this is the only way I see to get the result I understood Alex wanted. If that is what he wanted, he would have to run a second query once armed with output from the queries offered, so there's no real gain.
Good discussion. Thanks to all!
Use GROUP BY clause along with HAVING like
select "order", Product
from data
group by "order"
having count(distinct product) > 1;

SQL SUM with Repeating Sub Entries - Best Practice?

I hit this issue regularly but here is an example....
I have a Order and Delivery Tables. Each order can have one to many Deliveries.
I need to report totals based on the Order Table but also show deliveries line by line.
I can write the SQL and associated Access Report for this with ease ....
SELECT xxx
FROM
Order
LEFT OUTER JOIN
Delivery on Delivery.OrderNO = Order.OrderNo
until I get to the summing element. I obviously only want to sum each Order once, not the 1-many times there are deliveries for that order.
e.g. The SQL might return the following based on 2 Orders (ignore the banalness of the report, this is very much simplified)
Region OrderNo Value Delivery Date
North 1 £100 12-04-2012
North 1 £100 14-04-2012
North 2 £73 01-05-2012
North 2 £73 03-05-2012
North 2 £73 07-05-2012
South 3 £50 23-04-2012
I would want to report:
Total Sales North - £173
Delivery 12-04-2012
Delivery 14-04-2012
Delivery 01-05-2012
Delivery 03-05-2012
Delivery 07-05-2012
Total Sales South - £50
Delivery 23-04-2012
The bit I'm referring to is the calculation of the £173 and £50 which the first of which obviously shouldn't be £419!
In the past I've used things like MAX (for a given Order) but that seems like a fudge.
Surely there must be a regular answer to this seemingly common problem but I can't find one.
I don't necessarily need the code - just a helpful point in the right direction.
Many thanks,
Chris.
A roll up operator may not look pretty. However, it would do the regular aggregates that you see now, and it show the subtotals of the order. This is what you're looking for.
SELECT xxx
FROM
Order
LEFT OUTER JOIN
Delivery on Delivery.OrderNO = Order.OrderNo
GROUP BY xxx
WITH ROLLUP;
I'm not exactly sure how the rest of your query is set up, but it would look something like this:
Region OrderNo Value Delivery Date
North 1 £100 12-04-2012
North 1 £100 14-04-2012
North 2 £73 01-05-2012
North 2 £73 03-05-2012
North 2 £73 07-05-2012
NULL NULL f419 NULL
I believe what you want is called a windowing function for your aggregate operation. It looks like the following:
SELECT xxx, SUM(Value) OVER (PARTITION BY Order.Region) as OrderTotal
FROM
Order
LEFT OUTER JOIN
Delivery on Delivery.OrderNO = Order.OrderNo
Here's the MSDN article. The PARTITION BY tells the SUM to be done separately for each distinct Order.Region.
Edit: I just noticed that I missed what you said about orders being counted multiple times. One thing you could do is SUM() the values before joining, as a CTE (guessing at your schema a bit):
WITH RegionOrders AS (
SELECT Region, OrderNo, SUM(Value) OVER (PARTITION BY Region) AS RegionTotal
FROM Order
)
SELECT Region, OrderNo, Value, DeliveryDate, RegionTotal
FROM RegionOrders RO
INNER JOIN Delivery D on D.OrderNo = RO.OrderNo

SQL count query not returning correct results

Struggling getting a query to work……..
I have two tables:-
tbl.candidates:
candidate_id
agency_business_unit_id
tbl.candidate_employment_tracker
candidate_id
The candidate employment can have duplicate records of a candidate_id as it contains records on their working history for different clients.
The candidates tables is unique for each candidate.
I'm trying to obtain results which will group by agency_business_unit_id and count the amount of candidates each has which exist in the candidate_employment_tracker.
E.g.
Agency Business Unit Id | Candidates
------------------------------------------------------------
100 | 2
987 | 1
12 | 90
The query I'm working on doesn't appear to be working as I'm getting the count of the candidates in candidate_employment_tracker.
SELECT
abu.agency_business_unit_id,
abu.agency_business_unit_name,
count(c.candidate_id) AS candidateCount
FROM candidate_employment_tracker cet
INNER JOIN candidate c ON c.candidate_id = cet.candidate_id
INNER JOIN agency_business_unit abu ON abu.agency_business_unit_id = c.agency_business_unit_id
WHERE c.candidate_ni_number NOT REGEXP '^[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z] ?[0-9]{2} ?[0-9]{2} ?[0-9]{2} ?[ABCD]$'
GROUP BY abu.agency_business_unit_id
ORDER BY abu.agency_business_unit_name ASC
I've tried several approaches and the results are inconsistent. For instance I know one of the agency business units only has 1 candidate but the result is 2. This is as a result of this particular candidate having 2 records in the candidate employment tracker table. I'll keep bashing away but any help would be much appreciated.
Do you need
count(DISTINCT c.candidate_id)
That would avoid the double counting where candidates have 2 records in the candidate employment tracker table.
Hmmm this doesn't appear to work now that I look further into the results. When I compare the candidates for a agency business unit I get inconsistent count numbers.