Microsoft Access adding an extra column to existing union select - sql

[enter image description here][1]I need to add 4 columns ( Item name, FullPrice_2018(price), FullPrice_2019(price), (FullPrice_2019-FullPrice_2018) ) to the query. I can't figure out how to add another column to the union without merging rows.
Right now my table is with 2018 & 2019 items but I need 3 more columns.
https://i.stack.imgur.com/lTmqB.png
SELECT FullPrice_2018.[Item name]
FROM FullPrice_2018
UNION
SELECT FullPrice_2019.[Item name]
FROM FullPrice_2019
ORDER BY [Item name]
Result should be like this
"Item name" price2018 price2019 "price2019-price2018"
https://i.stack.imgur.com/XxKU5.png

Do you just want JOIN:
SELECT F2018.[Item name], F2018.FullPrice, F2019.FullPrice,
(F2019.FullPrice - F2018.FullPrice)
FROM FullPrice_2018 as F2018 INNER JOIN
FullPrice_2019 as F2019
ON F2018.[Item name] = F2019.[Item name]
ORDER BY F2018.[Item name];
Unfortunately, MS Access doesn't support FULL JOIN. But I think you can do:
SELECT [Item name], MAX(FullPrice_2018), MAX(FullPrice_2019),
(MAX(FullPrice_2019) - MAX(FullPrice_2018))
FROM (SELECT F2018.[Item name], F2018.FullPrice as FullPrice_2018, NULL as FullPrice_2010
FROM FullPrice_2018 as F2018
UNION ALL
SELECT F2019.[Item name], NULL, F2019.FullPrice as FullPrice_2019
FROM FullPrice_2019 as F2019
) F
GROUP BY [Item name]
ORDER BY [Item name];
Not all versions of MS Access support UNION ALL in the FROM clause, so you might need to use a view for that portion of the query.

Create a query that will return a normalised output:
SELECT
FullPrice_2018.[Item name], 2018 As [Year], Price
FROM
FullPrice_2018
UNION ALL
SELECT
FullPrice_2019.[Item name], 2019 As [Year], Price
FROM
FullPrice_2019
Save the query and use it as source in a normal crosstab query. Use the wizard to create this if you are unfamiliar with crosstab queries.

Related

SQL requery same table

I have a table that has a bunch of information:
Part Number, Category, Value, FreqL, FreqH, FREQ1, FREQ2.
I am trying to filter based on a user entry... Say they put in Part Number "xzy"
SELECT backup.Value, backup.FREQ1, backup.FREQ2
FROM backup
WHERE ((backup.[Part Number]) ="xyz";
I want to requery the table, but also include parts that fit all the same values resulting from xyz query.
I thought of using IN before my subquery, but that only limits to one column, how do i do all three?
Of course the below isn't working >
SELECT backup.[Part Number], backup.Value, backup.FreqL, backup.FreqH
FROM backup
WHERE (backup.Value AND backup.FREQ1 AND Backup.FREQ2) (
SELECT backup.Value, backup.FREQ1, backup.FREQ2, backup.CAT
FROM backup
WHERE ((backup.[Part Number]) ="xyz")
);
Any help is appreciated.
Thank you.
JR
I guess you need below query -
SELECT B1.[Part Number], B1.Value, B1.FreqL, B1.FreqH
FROM backup B1
JOIN (SELECT Value, FREQ1 , FREQ2
FROM backup
WHERE [Part Number] ="xyz") B2 ON B1.Value = B2.Value
AND B1.FREQ1 = B2.FREQ1
AND B1.FREQ2 = B2.FREQ2;
A typical method uses exists:
SELECT b.[Part Number], b.Value, b.FreqL, b.FreqH
FROM backup b
WHERE EXISTS (SELECT 1
FROM backup b2
WHERE b2.[Part Number] = 'xyz' AND
b2.Value = b.Value AND
b2.FREQ1 = b.FREQ1 AND
b2.FREQ2 = b.FREQ2
);
You don't say your platform, in DB2 tuples work -- like this:
SELECT backup.[Part Number], backup.Value, backup.FreqL, backup.FreqH
FROM backup
WHERE (backup.Value, backup.FREQ1, Backup.FREQ2) = (
SELECT backup.Value, backup.FREQ1, backup.FREQ2
FROM backup
WHERE ((backup.[Part Number]) ="xyz")
);

Asking to enter a parameter value that already exists

I have a three column table of price breaks called "FPB" that looks like this:
[Part Number] [Quantity] [Price]
AAA-AAAA     100   1.23
AAA-AAAA     200   1.15
BBB-BBBB     100   5.60
CCC-CCCC      500   3.21
....
Where each part number has multiple entries in multiple rows.
I'm trying to reorganize the table to look more like this
[Part Number] [Quantity1] [Price 1] [Quantity 2] [Price 2] [Quantity 3....
AAA-AAAA      100   1.23    200    1.15   ....
BBB-BBBB      100   5.60     ...
CCC-CCCC       500   3.21    ...
...
Where each part number has all its entries combined into one row. The first quantity column should have the lowest available quantity, the second should have the second smallest etc. I am trying to do this by first creating a 1-column table with just the unique part numbers using GROUP BY, and then creating more tables for each column that has the information I want in that column, and then joining it by Part Number. The problem comes when calculating the second smallest quantity for each type, done in the second to last section.
SELECT PNs.[Part Number], Q1T.Q1, P1T.Price, Q2T.Q2
FROM
(SELECT
[Part Number]
FROM FPB
GROUP BY [Part Number]
) AS PNs,
(SELECT
[Part Number],
MIN(Quantity) AS Q1
FROM FPB
GROUP BY [Part Number]
) AS Q1T,
(SELECT
*
FROM FPB
) AS P1T,
(SELECT
[Part Number],
MIN(IIF(Quantity>Q1T.Q1,Quantity)) AS Q2
FROM FPB
GROUP BY [Part Number]
) AS Q2T
WHERE
PNs.[Part Number] = Q1T.[Part Number]
AND P1T.[Part Number] = PNs.[Part Number]
AND P1T.Quantity = Q1T.Q1
AND Q2T.[Part Number] = PNs.[Part Number]
When I run this query, it asks me to enter a parameter value for Q1T.Q1, even though it already exists. If I remove the code section for Q2T, as well as any references to Q2, it will work without a problem, and it won't ask about a value for the other instances of Q1T.Q1. Why doesn't Q1T.Q1 have a value just for that section, and how can I fix it? As a side note, I'm using the SQL features of a program called PHPRunner, and its client doesn't support UPDATE/DELETE/INSERT/CREATE queries, UNION, and DISTINCT.
You're looking for something like this.
select
p1.PartNumber,
ifnull(max(p2.Quantity), 0) + 1 as LowerQuantity,
p1.Quantity as UpperQuantity,
p1.Price,
count(p2.PartNumber) + 1 as PriceTier
from
FPB p1 left outer join FPB p2
on p2.PartNumber = p1.PartNumber and p2.Quantity < p1.Quantity
From there it's easy to pivot in order to insert into a new table:
into into NewFPB (PartNumber, Quantity1, Price1, Quantity2, Price2, ...)
select
PartNumber,
min(switch(PriceTier = 1, UpperQuantity)) as Quantity1,
min(switch(PriceTier = 2, UpperQuantity)) as Quantity2, ...
min(switch(PriceTier = 1, Price)) as Price1,
min(switch(PriceTier = 2, Price)) as Price2, ...
from (
select
p1.PartNumber,
ifnull(max(p2.Quantity), 0) + 1 as LowerQuantity,
p1.Quantity as UpperQuantity,
p1.Price,
count(p2.PartNumber) + 1 as PriceTier
from
FPB p1 left outer join FPB p2
on p2.PartNumber = p1.PartNumber and p2.Quantity < p1.Quantity
) data
You might have to tweak it a little bit for Access to accept it. But the core ideas are there.
The query you call is incorrect.
Q1T is inner select statement , and in Q2T (other inner select statement) , you can't use any field from Q1T
The SQL Server raise error: Incorrect syntax near ')'.
To overcome this limitation , you should use Common Table Expressions CTE
for PNs, Q1T, P1T, Q2T
CTE is like dynamic view.
It's a new feature since sql 2008 and It's a very powerful.
review: https://technet.microsoft.com/en-us/library/ms190766(v=sql.105).aspx
Try to Draw a relational data model for these four CTE to be sure that a relation exist between them based on your where conditions.
I think the logic in this query may raise runtime error during execution:
e.g. The multi-part identifier "Q1T.Q1" could not be bound.
Edit:
For Ms-Access you can create four queries for: PNs, Q1T, P1T, Q2T every one is in a separate query, and the fifth query join these queries and add where conditions.
In this case you will not get any syntax error. and will get Data model with relation free :) .
As per your question, by the time you define the derived table Q2T, Q1T is still an invalid object. You need to try to work around this issue.
EDIT:
Suppose you only got 2-level columns to handle, the code is listed below, i tested it. It works well.
select q5.*,q3.quantity, q3.price
from
(select *
from FPB as Q1
where 0 = (select count(distinct(quantity)) from FPB as Q2 where Q2.quantity < Q1.quantity AND Q2.[part number] = Q1.[part number])) as Q5
,
(
select distinct(temp.[part number]),Q2.quantity, Q2.price from FPB as temp
left join
(select *
from FPB as Q4
where 1 = (select count(distinct(quantity)) from #test as Q2 where Q2.quantity < Q4.quantity AND Q2.[PART NUMBER] = Q4.[PART NUMBER])) as Q2
on temp.[PART NUMBER] = Q2.[PART NUMBER]
) as Q3
where Q5.[PART NUMBER] = Q3.[PART NUMBER]

Putting two SQL statements together

I am new at SQL and I am just trying to add two SQL statements together which are below. The first table is a basic make table pulling in only fields I need and then the second table is pulling the same information but appending it to the first table I made in Step 1 . I have been doing some research and what I think I need to do is a union query but I am not sure how to go about that any help please?
/*first step*/
/*Select
[NPI],
[Last Name],
[First Name],
[Middle Name],
Suffix,
Gender,
[Spoken Languages]
Into [Provider Table]
From sylvia.dbo.UNIQUEACN*/
/*Second step appending PCCN Providers*/
Insert into [sylvia].dbo.[provider Table] ( NPI, [Last Name], [First Name], [Middle Name], Suffix, Gender, [spoken languages] )
Select sylvia.dbo.[PCCNProviders].NPI, sylvia.dbo.PCCNProviders.[Last Name],sylvia.dbo.PCCNProviders.[First Name], sylvia.dbo.PCCNProviders.[Middle Name], sylvia.dbo.PCCNProviders.suffix, sylvia.dbo.PCCNProviders.gender, sylvia.dbo.PCCNProviders.[Spoken Languages]
From sylvia.dbo.[PCCNproviders];
Because your 2 tables have the same number and order of columns, you can simply execute the below query. Use UNION ALL if you want to keep duplicated values from both tables or just UNION if you want all duplicated values to be removed.
SELECT *
-- INTO [Combined_table]
FROM sylvia.dbo.UNIQUEACN
UNION ALL
SELECT *
FROM sylvia.dbo.[PCCNproviders]
Thank you I did just that I did a union query and its way cleaner then what I was doing .. Thanks again!! Ive been doing SQL for a week and as you can tell its a struggle but getting there
Select
a.[NPI],
a.[Last Name],
a.[First Name],
a.[Middle Name],
a.Suffix,
a.Gender,
a.[Spoken Languages]
Into [Provider test]
From sylvia.dbo.UNIQUEACN a
Union
Select
b.[NPI],
b.[Last Name],
b.[First Name],
b.[Middle Name],
b.Suffix,
b.Gender,
b.[Spoken Languages]
From sylvia.dbo.[PCCNproviders] b

Have blank fields in query on purpose

I have a Microsoft Access database with the following table:
TableName: Parts
Cabinet ID - Number
Part ID - Number
PartClass - Number
Width - Number (double)
Length - Number (double)
Description - Text
I use the following SQL queries to get three views:
DoorPanels:
SELECT Parts.[Cabinet ID], Count(Parts.[Cabinet ID]) as Qty, Parts.Description as Name Parts.Width, Parts.Length
FROM Parts
WHERE PartClass=13 GROUP BY Parts.[Cabinet ID], Parts.Description, Parts.Width, Parts.Length
ORDER BY Parts.[Cabinet ID]
DoorRails:
SELECT Parts.[Cabinet ID], Count(Parts.[Cabinet ID]) as Qty, Parts.Description as Name Parts.Width, Parts.Length
FROM Parts
WHERE PartClass=14 GROUP BY Parts.[Cabinet ID], Parts.Description, Parts.Width, Parts.Length
ORDER BY Parts.[Cabinet ID]
DoorStiles:
SELECT Parts.[Cabinet ID], Count(Parts.[Cabinet ID]) as Qty, Parts.Description as Name Parts.Width, Parts.Length
FROM Parts
WHERE PartClass=15 GROUP BY Parts.[Cabinet ID], Parts.Description, Parts.Width, Parts.Length
ORDER BY Parts.[Cabinet ID]
This gives me three separate views that hold only the parts that I want. Now, I have an additional table:
TableName: Doors
Cabinet ID - Number
Door ID - Number
Width - Number (double)
Height - Number (double)
I use another query to create a view for this as well:
SELECT Doors.[Cabinet ID], Count(Doors.[Door ID]) as Qty FROM Doors GROUP BY Doors.[Cabinet ID] ORDER BY Doors.[Cabinet ID]
So, finally I want to join all of these together...but this is where I am at a bit of a loss. What I need to get, would be a result like this, from the data that I have retrieved:
Doors.[Cabinet ID] Doors.Qty DoorRails.* DoorStiles.* DoorPanels*
1 2 [data] [data] [data]
[data] [data] [data]
2 3 [data] [data] [data]
[data] [data] [data]
[data] [data] [data]
Now, to decipher what I am talking about in the result above, you can see that for [Cabinet ID] 1, I have a door quantity of 2, so I need 2 records for the parts for that door. [Cabinet ID] 2 has 3 doors, so I need 3 records for all the door parts for that.
Now, I understand that this is a little complicated, and possibly...well...impossible, but I have been working on this for a few days and haven't come up with anything. If it's not possible, I would appreciate the experts here telling me so.
Just for FYI - I can't make ANY changes to the database or the structure, all that I can do is run Queries against it.
I think the easiest way to do this would be via a Cartesian join to a table that simply has rows with a single field incrementing from 1 to the maximum number of doors you will ever need. For example,
Counter.Num
-----------
1
2
3
If you cannot even create local tables for your own use, you could simulate the above using a UNION query. Access has some limitations here, so you'll need to reference an existing table even though you won't use any of its rows. For example,
SELECT TOP 1 1 AS Num FROM msysobjects
UNION ALL
SELECT TOP 1 2 AS Num FROM msysobjects
UNION ALL
SELECT TOP 1 3 AS Num FROM msysobjects
Then use this Counter table/query as follows:
SELECT D.[Cabinet ID], C.Num & " of " & Count(D.[Door ID]) AS [Door Number],
DR.*, DS.*, DP.*
FROM Counter AS C,
((Doors AS D INNER JOIN DoorRails AS DR ON D.CabinetID=DR.CabinetID)
INNER JOIN DoorStiles AS DS ON D.CabinetID=DS.CabinetID)
INNER JOIN DoorPanels AS DP ON D.CabinetID=DP.CabinetID
WHERE C.Num <= Count(D.[Door ID])
GROUP BY D.[Cabinet ID]
ORDER BY D.[Cabinet ID], C.Num
This will be a slightly different result than your sample. The difference is the Cabinet ID will be repeated for each door. Since the quantity would also be repeated, I substituted the door number instead (in the form of "1 of 2", "2 of 2", etc.).

Entire Union query returns no results if part of it returns no results

I've created the folllowing Union query, which works fine most of the time:
SELECT [%$###_Alias].[Contact ID], [%$###_Alias].[Mailing Name]
FROM (SELECT [Referrals - Contacts Within Organisations].[Contact ID], [Referrals - Contacts Within Organisations].[Mailing Name], [Referrals - Contacts Within Organisations].[Surname], [Referrals - Contacts Within Organisations].[First name]
FROM [Referrals - Contacts Within Organisations]
UNION SELECT "0" as [Contact ID], "View all contacts" as [Mailing Name], "0" as [Surname], "0" as [First name]
FROM [Referrals - Contacts Within Organisations]) AS [%$###_Alias]
ORDER BY [%$###_Alias].Surname, [%$###_Alias].[First name];
This adds an initial row of "View all contacts" at the top of whatever the query returns.
However, if the "actual" query part of it returns no results, the entire query returns no results, whereas I'd always want the initial row to appear regardless.
Is this possible, and if so, what am I doing wrong? Thanks.
EDIT: Thanks all for your help. The final working query is below for reference of anyone else who needs this sort of thing:
SELECT A.[Contact ID], A.[Mailing Name]
FROM (SELECT "0" as [Contact ID], "View all contacts" as [Mailing Name], "0" as [Surname], "0" as [First name]
FROM [Dummy]
UNION
SELECT [Referrals - Contacts Within Organisations].[Contact ID], [Referrals - Contacts Within Organisations].[Mailing Name], [Referrals - Contacts Within Organisations].[Surname], [Referrals - Contacts Within Organisations].[First name]
FROM [Referrals - Contacts Within Organisations]) AS A
ORDER BY A.Surname, A.[First name];
To return always one row with data in SQL, even when you are manually providing the values, you need to be selecting from a table that has at least one row, I suggest using a tblDummy with one field of random information.
e.g:
SELECT "Hello", "Goodbye"
FROM tblDummy
As a side note I would also try and get rid of:
[%$###_Alias]
This can be accomplished by aliasing your Derived tables by adding:
(SELECT * FROM Blah) AS A
for example to name the derived table as A