SQL Lookup in MS Access Query - sql

I have an Access Database with a table [Inventory] with following fields:
[Inventory].[Warehouse]
[Inventory].[PartNumber]
I also have a query [TransactionsQry] with following fielfd:
[TransactionsQry].[PartNumber]
[TransactionsQry].[SumofTransactions]
Now I would like to make a new query which shows all part numbers per Warehouse (from table [Inventory]) and look up related (number of) transactions in query [TransactionsQry]. Not every part number in [Inventory] has transactions yet and if so I would like to display "0".
At first I successfully tried this with a DLookup, but the result is a very slow query for very little data.
That is why I tried the following (but unsuccessfully displaying only matched part numbers and an additional error message):
SELECT
Inventory.Warehouse AS Warehouse,
TransactionsQry.PartNumber AS PartNumber,
TransactionsQry.SumofTransactions AS SumofTransactions
FROM Inventory
INNER JOIN TransactionsQry ON Inventory.PartNumber = TransactionsQry.PartNumber;
Any help with solving this issue in SQL is highly appreciated. Thanks.

You would be needing a LEFT JOIN based on what you need. Along with a Nz to treat Nulls as 0. Here is the corrected CODE
SELECT
Inventory.Warehouse AS Warehouse,
TransactionsQry.PartNumber AS PartNumber,
Nz(TransactionsQry.SumofTransactions, 0) AS SumofTransactions
FROM
Inventory LEFT JOIN TransactionsQry
ON
Inventory.PartNumber = TransactionsQry.PartNumber;

You want to use left join rather than inner join for this. Also, table aliases make queries easier to read and write:
SELECT i.Warehouse AS Warehouse,
tq.PartNumber AS PartNumber,
nz(tq.SumofTransactions, 0) AS SumofTransactions
FROM Inventory as i LEFT JOIN
TransactionsQry as tq
ON i.PartNumber = tq.PartNumber;
However, I'm guessing that you really want a group by:
SELECT i.Warehouse AS Warehouse,
tq.PartNumber AS PartNumber,
nz(sum(tq.SumofTransactions), 0) AS SumofTransactions
FROM Inventory as i LEFT JOIN
TransactionsQry as tq
ON i.PartNumber = tq.PartNumber
GROUP BY i.Warehouse, tq.PartNumber;

Related

Designing query to select count from different tables

This is the schema for my questions
Hi, I don't have experience in SQL Developer and I'm trying to build a query for the following question:
I need that for each DVD in the catalog, display the title, length, release_date, and how many times it has been checked out by all customers across all libraries.
Also I want to include those that have not been checked out yet displaying 0, and sort results by title.
So far I have this in the query but I'm stock here:
--Question C. ************* VERIFY
Select
Catalog_Item.Title,
DVD.Length,
Catalog_Item.Release_Date,
(
Select
Count(Transaction.Transaction_ID)
From Transaction
Where
DVD.Catalog_Item_ID = Physical_Item.Catalog_Item_ID
And Physical_Item.Physical_Item_ID = Transaction.Physical_Item_ID
) as "Total_DVD"
From
Catalog_Item,DVD,
Physical_Item
Group by
Catalog_Item.Title,
DVD.Length,
Catalog_Item.Release_Date
If I run this exact query I get error
Not a Group By Expression
And if I exclude the GROUP BY, I get results by doesn't look like the correct outputs.
Any suggestions on what syntax I can use to achieve the desired output? Thanks!
You put three tables to the query but you missed to link them. If you don't link them, you will see too much-duplicated rows.
Also, your sub-query links were wrong, I assume you tried to put the links here that you missed in the main query.
I believe you need something like that:
Select
CI.Title
,DVD.Length
,CI.Release_Date
,NVL(TR.TotalTransactions,0) TotalTransactions
From Catalog_Item CI
INNER JOIN DVD ON DVD.Catalog_Item_ID = CI.Catalog_Item_ID
LEFT JOIN Physical_Item PHI ON CI.Catalog_Item_ID = PHI.Catalog_Item_ID
LEFT JOIN (SELECT Physical_Item_ID
, Count(Transaction_ID) TotalTransactions
FROM Transaction
GROUP BY Physical_Item_ID
) TR ON PHI.Physical_Item_ID = TR.Physical_Item_ID
For a start, join Catalog_Item, Physical_Item and DVD together. Without appropriate join conditions, these three tables will join using a cartesian product join - which is probably one of the reasons why you are seeing unexpected results.

Specifying SELECT, then joining with another table

I just hit a wall with my SQL query fetching data from my MS SQL Server.
To simplify, say i have one table for sales, and one table for customers. They each have a corresponding userId which i can use to join the tables.
I wish to first SELECT from the sales table where say price is equal to 10, and then join it on the userId, in order to get access to the name and address etc. from the customer table.
In which order should i structure the query? Do i need some sort of subquery or what do i do?
I have tried something like this
SELECT *
FROM Sales
WHERE price = 10
INNER JOIN Customers
ON Sales.userId = Customers.userId;
Needless to say this is very simplified and not my database schema, yet it explains my problem simply.
Any suggestions ? I am at a loss here.
A SELECT has a certain order of its components
In the simple form this is:
What do I select: column list
From where: table name and joined tables
Are there filters: WHERE
How to sort: ORDER BY
So: most likely it was enough to change your statement to
SELECT *
FROM Sales
INNER JOIN Customers ON Sales.userId = Customers.userId
WHERE price = 10;
The WHERE clause must follow the joins:
SELECT * FROM Sales
INNER JOIN Customers
ON Sales.userId = Customers.userId
WHERE price = 10
This is simply the way SQL syntax works. You seem to be trying to put the clauses in the order that you think they should be applied, but SQL is a declarative languages, not a procedural one - you are defining what you want to occur, not how it will be done.
You could also write the same thing like this:
SELECT * FROM (
SELECT * FROM Sales WHERE price = 10
) AS filteredSales
INNER JOIN Customers
ON filteredSales.userId = Customers.userId
This may seem like it indicates a different order for the operations to occur, but it is logically identical to the first query, and in either case, the database engine may determine to do the join and filtering operations in either order, as long as the result is identical.
Sounds fine to me, did you run the query and check?
SELECT s.*, c.*
FROM Sales s
INNER JOIN Customers c
ON s.userId = c.userId;
WHERE s.price = 10

Join Statements in Access SQL

I'm new with SQL and how it works with Access, and I had a problem with a query only returning items from a specific set.
So according to the definitions I read a LEFT JOIN statement is supposed to return all records from the Left table then only specific records from the Right table. For some reason it will not return all records from my left table. Please see code below. It still somehow wants to only return records that have some kind of relationship. Any Ideas? I want all records from my left table ( tbl_historicOrg) to be returned then only specific records from the Right table.
SELECT tbl_historicOrg.NAME, tbl_historicOrg.Racf, tbl_historicOrg.STATUS, tbl_historicOrg.PCF, tbl_historicOrg.[Date Finalized], tbl_historicOrg.[Hist Month], import_data.SCHDLE_EXCPT_NM, import_data.HOURS
FROM tbl_historicOrg LEFT JOIN import_data ON tbl_historicOrg.Racf = import_data.RACF
WHERE (((import_data.SCHDLE_EXCPT_NM)="System Problems"));
Any suggestions or corrections would be greatly appreciated.
Try like below; get the filtered data and do a JOIN with that result set
SELECT tbl_historicOrg.NAME,
tbl_historicOrg.Racf,
tbl_historicOrg.STATUS,
tbl_historicOrg.PCF,
tbl_historicOrg.[Date Finalized],
tbl_historicOrg.[Hist Month],
tab.SCHDLE_EXCPT_NM,
tab.HOURS
FROM tbl_historicOrg
LEFT JOIN (
select SCHDLE_EXCPT_NM,
HOURS,
RACF
from import_data where SCHDLE_EXCPT_NM = "System Problems" ) as tab
ON tbl_historicOrg.Racf = tab.RACF;
Your query should be like below, Dont use 'WHERE' clause for second table, its filtering the data for 'import_data.SCHDLE_EXCPT_NM = "System Problems"'
SELECT tbl_historicOrg.NAME, tbl_historicOrg.Racf, tbl_historicOrg.STATUS,
tbl_historicOrg.PCF, tbl_historicOrg.[Date Finalized], tbl_historicOrg.[Hist Month],
import_data.SCHDLE_EXCPT_NM, import_data.HOURS
FROM tbl_historicOrg LEFT JOIN import_data ON tbl_historicOrg.Racf = import_data.RACF

Combining data from multiple tables issue Oracle 11g

TABLE // FIELD
Customer // Company
Stock // Description
Manufact // Manu_Name
Items // Quantity, total_price
I am using Oracle 11g Application Express. I need to display a list of each stock ordered for EACH CUSTOMER. I need to display the Manufacturer, quantity ordered, and total price paid.
When I run this query within my SQL*PLUS command prompt, it endlessly displays results from the tables mentioned until I force-quit (ctrl+c) the application. This is incredibly frustrating - I've tried joining tables, using the EXISTS clause, I just don't know what the hell to do. Any insight would be wonderful - not looking for someone to simply solve this for me, more-so just guide me.
SELECT c.company, s.description, m.manu_name, i.quantity, i.total_price
FROM db1.customer c JOIN db1.orders o USING (customer_num), db1.stock s, db1.manufact m, db1.items i
WHERE o.order_num = i.order_num;
This causes a never-ending display of what seems like the same results, over, and over, and over.
Essentially, I need to display the required information for EACH ORDER of stock. However, I don't need the order_num in my output display of columns, so I thought I needed to use the order_num (in db1.orders o & db1.items i) to essentially tell Oracle, "For each order_num (an order can't exist without an order_num), display (results)...
I am incredibly lost - I've tried outer joins, I've tried using an EXIST operator, I am just stumped and I feel like it's something easy that I'm overlooking.
EDIT: So, it seems I finally found it, after an enormous amount of pondering.
This is how I did it, in case anyone else runs into this issue:
SELECT c.company, s.description, m.manu_name, i.quantity, i.total_price
FROM db1.customer c JOIN db1.orders o USING (customer_num)
JOIN db1.items i USING (order_num)
JOIN db1.stock USING (stock_num)
JOIN db1.manufact m ON m.manu_code = s.manu_code
ORDER BY c.company, s.description;
If you JOIN db1.manufact m USING (manu_code), you get an ambiguously defined column error from Oracle - this is because I already joined the other tables and that column was in one of them (It was the db1.stock table). You can still join them, but you have to use JOIN ON instead.
This displayed the results I needed. Thanks anyways, and cheers if this helped anybody out!
You've only provided two joins (one USING and one in the WHERE) between 5 tables - in this case, you will get the cartesian product of all other rows in all other tables, hence the large number of rows.
(Edit, by implication you need to join all tables together, whether by USING or JOIN)
In order to use the USING join sugar, the same column must be present on the immediate lhs and rhs tables. For multiple joins, into a hierarchy, you may need to nest the USINGs like so:
SELECT c.company, s.description, m.manu_name, i.quantity, i.total_price
FROM customer c
JOIN orders o
JOIN stock s
JOIN items i
JOIN manufact m USING(manid)
USING(itemid)
USING (stockid)
USING (customer_num);
There where join isn't needed since we already have the USING join
I've assumed some columns and relationships between your table in this fiddle here:
You can also drop the USING and use explicit JOIN syntax, which will allow you to avoid the nesting (this is also more portable across the ANSI world):
SELECT c.company, s.description, m.manu_name, i.quantity, i.total_price
FROM customer c
INNER JOIN orders o on c.customer_num = o.customer_num
INNER JOIN stock s on o.stockid = s.stockid
INNER JOIN items i on i.itemid = s.itemid
INNER JOIN manufact m on m.manid = i.manid;
Edit
As OP has demonstrated, no requirement to nest the USING joins, provided that the join ordering is sensible, and provided that the FK JOIN column isn't duplicated across multiple tables.
http://sqlfiddle.com/#!4/91ef6/9

SQL count - first time

I am learning SQL (bit by bit!) trying to perform a query on our database and adding in a count function to show the total orders that appear against a customers id by counting in a inner join query.
Somehow it is pooling all the data together onto one customer with the count function though.
Can someone please suggest where I am going wrong?
SELECT tbl_customers.*, tbl_stateprov.stprv_Name, tbl_custstate.CustSt_Destination, COUNT(order_id) as total
FROM tbl_stateprov
INNER JOIN (tbl_customers
INNER JOIN (tbl_custstate
INNER JOIN tbl_orders ON tbl_orders.order_CustomerID = tbl_custstate.CustSt_Cust_ID)
ON tbl_customers.cst_ID = tbl_custstate.CustSt_Cust_ID)
ON tbl_stateprov.stprv_ID = tbl_custstate.CustSt_StPrv_ID
WHERE tbl_custstate.CustSt_Destination='BillTo'
AND cst_LastName LIKE '#URL.Alpha#%'
You need a GROUP BY clause in this statement in order to get what you want. You need to figure out what level you want to group it by in order to select which fields to add to the group by clause. If you just wanted to see it on a per customer basis, and the customers table had an id field, it would look like this (at the very end of your sql):
GROUP BY tbl_customers.id
Now you can certainly group by more fields, it just depends how you want to slice the results.
In your select statement you are using format like tableName.ColumnName but not for COUNT(order_id)
It should be COUNT(tableOrAlias.order_id)
Hope that helps.
As you are new to SQL it might also be worth considering the readability of your joins - the nested / bracketed joins you mentioned above are quite hard to read, and I would also personally alias your tables to make the query that bit more accessible:
SELECT
tbl_customers.customer_id
,tbl_stateprov.stprv_Name
,tbl_custstate.CustSt_Destination
,COUNT(order_id) as total
FROM tbl_stateprov statep
INNER JOIN tbl_custstate state ON statep.stprv_ID = state.CustSt_StPrv_ID
INNER JOIN tbl_customers customer ON customer.cst_ID = state.CustSt_Cust_ID
INNER JOIN tbl_orders orders ON orders.order_CustomerID = state.CustSt_Cust_ID
WHERE tbl_custstate.CustSt_Destination='BillTo'
AND cst_LastName LIKE '#URL.Alpha#%'
GROUP BY
tbl_customers.customer_id
,tbl_stateprov.stprv_Name
,tbl_custstate.CustSt_Destination
--And any other columns you want to include the count for