Need to get description of a different column in my SQL query - sql

The table I'm working with has 8 different columns, I'm working with three called course_no, prerequisite, and description. the prerequisite shows what is needed to get into the course_no and the description currently shows the course_no description. I however need to get the description of the prerequisite while still showing the course_no. I am unsure of how to do this. I've looked up inner joins but they don't seem to be what im looking for. This is the sql statement just need to help figuring out how to show the description for the prerequisite column rather than course_no column.
SELECT course_no, prerequisite, description
FROM course

I think join is what you are looking for. Perhaps:
select c.*, p.description as prerequisite_description
from course c left join
course p
on c.prerequisite = p.course_no;

That would make more sense, the left join will course records even where there is no linked prerequisite, this will also show the course record multiple times if there is more than one matching record
SELECT c.course_no, c.description, NVL(p.description, '') as prerequisite_description
FROM course c
LEFT JOIN course p ON c.prerequisite = p.course_no;
If you only want 1 result row for each course, you could group concat the prerequisite descriptions
SELECT c.course_no, c.description, NVL(LISTAGG(p.description, ', ') WITHIN GROUP (ORDER BY p.course_no), '') as prerequisite_description
FROM course c
LEFT JOIN course p ON c.prerequisite = p.course_no
GROUP BY c.course_no, c.description;

Related

What letters are written before column titles

I'm learning SQL language using online resources, but mostly using queries that my predecessors have written at my company. I'm editing fields correspondingly to produce the correct results. But I want to understand more.
I have a few questions about this section of code.
1. Why is there a "p" before TrackingNumber, and oh/cc/im in front of others?
It seems to matter which I choose, so I just use trial and error until it runs.
2. Why do I need to have tracking number - when I delete this line, the code won't run!
select
p.TrackingNumber
,im.Sku
,oh.BusinessUnitCode
,cc.Qty
,oh.ShipCode
,oh.OrigShipCode
,oh.Store
,convert(date,oh.ShipTime) as 'OrderDate'
,oh.ShipToName
,oh.OrderNumber
from dmhost.tblOrderHeader oh
join dmhost.tblContainer c on oh.OrderHeaderID = c.OrderHeaderID
join dmhost.tblPackage p on c.ContainerID = p.ContainerID
join dmhost.tblContainerContents cc on c.ContainerID = cc.ContainerID
join dmhost.tblItemMaster im on im.ItemMasterID = cc.ItemMasterID
where (oh.ShipTime between '04/07/2019' and '05/05/2019')
The letters you talk about are referring to table names (or aliases).
Example using aliases would be:
SELECT c.customerName, o.orderNumber from Customers c
INNER JOIN Orders o on c.id=o.customerid
Same query without aliases:
SELECT Customers.customerName, Orders.orderNumber from Customers
INNER JOIN Orders on Customers.id=Orders.customerid
or omitting table names
SELECT customerName, orderNumber from Customers
INNER JOIN Orders on Customers.id=Orders.customerid
The table denomination is specially important when you retrieve columns with the same name from different table. For example id from Customers and id from Orders
SELECT c.id as CustomerId, o.id as OrderId from Customers c
INNER JOIN Orders o on c.id=o.customerid
The bits before the dot (.) in your field names are table aliases. If you look in the FROM clause of this query you should see these abbreviations in front of the various tables listed in there. They're used to
a) make it less tedious to type table names and
b) make it unambiguous which table you are selecting the column from (this both increases readability of the code and also deals with any cases where two of the tables have columns with the same name)
Here's a simple example of table alias usage:
SELECT emp.ID, emp.Name, dep.ID, dep.Name
FROM employees emp
INNER JOIN departments dep ON dep.ID = emp.DepartmentID
Here you can see that the employees and departments tables have each got aliases to shorten their name. In the query we refer to each field using it's alias. This is especially useful since both tables have fields called "ID" and "Name".
As for why it crashes when you remove p.TrackingNumber, it's likely because you did not also remove the comma (,) from the next line. The comma is used to mark where the name of the next field begins - it could be at the end of the previous line, rather than the start of the next one. Clearly you can't start the list of fields with a comma, because there is no field name preceding it - hence you get a syntax error.
The same query could have been written
select
p.TrackingNumber,
im.Sku,
oh.BusinessUnitCode,
-- etc
which might make it easier to see the usage of the comma.

Need date of latest input invoice by Vendor/Supplier

This query works. I´m trying to find the most recent date of Document input in our system.
The query below brings the date and supplier number, and it's working perfectly.
SELECT SUPPLIERNUMBER, MAX(DATEOFINPUT)
FROM TABLE A
WHERE COUNTRY IN ('661')
AND COMPANY IN ('01','40')
GROUP BY SUPPLIERNUMBER
Now, that information is great by itself, but I will also need additional information that it´s in another table B (the one that holds the information from the Suppliers, like Name, Short Name, Bank Data, etc)
SELECT B.COUNTRY , B.COMPANY ,B.SUPPLIERNUMBER,
B.SUPPLIERNAME, A.DATEOFINPUT
FROM A
INNER B
ON A.COUNTRY =B.COUNTRY
AND A.COMPANY =B.COMPANY
Here is where I don't know how to mix the 2 queries together. I understand I need from the first Query 2 columns of information: SupplierNumber and DateofInput.
With this information I have to join with the other table to get the Supplier information.
I'm not sure how to do this. I thought I had to do a subquery with MAX(DateofInput) but that way it will only bring 1 record of several with the same date, but no way to also bring the SupplierNumber.
Could you folk help me please?
This is for DB2, maybe some SQL syntax won´t work, not sure.
I only have user privileges, not admin access.
Incorporate the data fields from SUPPLIER table (B) into the SELECT and include them in the GROUP BY clause:
SELECT A.SUPPLIERNUMBER,
B.SUPPLIERNAME, B.COUNTRY, B.COMPANY, MAX(DATEOFINPUT) AS MAXDATE
FROM TABLE A
INNER JOIN SUPPLIER B
ON A.SUPPLIERNUMBER = B.SUPPLIERNUMBER
WHERE A.COUNTRY IN ('661')
AND A.COMPANY IN ('01','40')
GROUP BY A.SUPPLIERNUMBER, B.SUPPLIERNAME, B.COUNTRY, B.COMPANY

Avoid full scan for subquery

I have a query which was working before I added the exist condition. After adding the exist condition , its going into loop forever and not getting back any results. I think the main reason for that is the full scan for every row level record. Can anyone please tell how to avoid that. The query below is an example of what I am trying to achieve.
Basically the condition is that a car can have many parts and if any one of the parts updated on changes for that car, we want to pick up all the parts. The part has detail table and I want to look at updates to the detail table.
select c.id, p.id
from car c join part p on p.car_id=c.id
where exists (
select 1
from part p join pdetl pd on p.id=pd.part_id
where p.car_id=c.id and pd.updated_on > ?
)
EDITED: Modified the query to get all the parts associated to the car that had part(s) updated.
The inner query gets the parts that were updated. The outer query then pulls all the parts that are associated to the car:
select c.id, p.id
from car c join part p on p.car_id=c.id
where c.id in
(
select c.id
from car c join part p on p.car_id=c.id
where exists (
select 1
from pdetl pd
where p.id=pd.part_id
and pd.updated_on > ?
)
)

distinct group by join problem

Here's what I want to achieve:
I have a number of categories, each one with products in it.
I want to produce a report that shows various information about those products for each category. So I have a query that looks something like:
select
category,
count(products),
sum(product_price),
from product
group by category
So far so good.
But now I also want to get some category-specific information from a table that has information by category. So effectively I want to say:
join category_info on category
except that that will create a join for each row of each group, rather than just one join for each group.
What I really want to be able to say to sql is 'for each group, take the distinct category value, of which there's guaranteed to only be one since I'm grouping on it, and then use that to join to the category info table'
How can I accomplish this in SQL? By the way, I'm using Oracle 10g..
Many thanks!
select a.category, a.Count, a.SumPrice
ci.OtherColumn
from (
select p.category,
count(p.products) as Count,
sum(p.product_price) as SumPrice,
from product p
group by category
) a
inner join category_info ci on a.category = ci.category

Select based on the number of appearances of an id in another table

I have a table B with cids and cities. I also have a table C that has these cids with extra information. I want to list all the cids in table C that are associated with ALL appearances of a given city in Table B.
My current solution relies on counting the number of times the given city appears in Table B and selecting only the cids that appear that many times. I don't know all the SQL syntax yet, but is there a way to select for this kind of pattern?
My current solution:
SELECT Agents.aid
FROM Agents, Customers, Orders
WHERE (Customers.city='Duluth')
AND (Agents.aid = Orders.aid)
AND (Customers.cid = Orders.cid)
GROUP BY Agents.aid
HAVING count(Agents.aid) > 1
It only works because I know right now with the HAVING statement.
Thanks for the help. I wasn't sure how to google this problem, since it's pretty specific.
EDIT: I'm pinpointing my problem a bit. I need to know how to determine if EVERY row in a table has a certain value for a field. Declaring a variable and counting the rows in a sub-selection and filtering out my results by IDs that appear that many times works, but It's really ugly.
There HAS to be a way to do this without explicitly count()ing rows. I hope.
Not an answer to your question, but a general improvement.
I'd recommend using JOIN syntax to join your tables together.
This would change your query to be:
SELECT Agents.aid
FROM Agents
INNER JOIN Orders
ON Agents.aid = Orders.aid
INNER JOIN Customers
ON Customers.cid = Orders.cid
WHERE Customers.city='Duluth'
GROUP BY Agents.aid
HAVING count(Agents.aid) > 1
What variant of SQL are you using?
To start with, you can (and should) use JOIN instead of doing it in the WHERE clause, e.g.,
select Agents.aid
from Agents
join Orders on Agents.aid = Orders.aid
join Customers on Customers.cid = Orders.cid
where Customers.city = 'Duluth'
group by Agents.aid
having count(Agents.aid) > 1
After that, I'm afraid I might be a little lost. Using the table names in your example query, what (in English, not pseudocode) are you trying to retrieve? For example, I think your sample query is retrieving the PK for all Agents that have been involved in at least 2 Orders involving Customers in Duluth.
Also, some table definitions for Agents, Orders, and Customers might help (then again, they might be irrelevant).
I'm not sure if I understood you problem, but I think the following query is what you want:
SELECT *
FROM customers b
INNER JOIN orders c USING (cid)
WHERE b.city = 'Duluth'
AND NOT EXISTS (SELECT 1
FROM customers b2
WHERE b2.city = b.city
AND b2.cid <> cid);
Probably you will need some indexes on these columns.