MS Access + SQL - Left join on switch statement? - sql

I have a switch statement in a crosstab query:
Switch([Age]<20, "Under 20", [Age]>=20 and <=25, "Between 20 and 25")
AS **Age_Range**
The switch statement evaluates my row heading like this:
1 2 3 4 5 <-- Columns
Under 20 0 0 0 3 2
Between 20 and 25 1 2 0 4 0
Where the value =
Total: Nz(Count(Demo.ID))+0
Okay, all is good so far. However, I am trying to make a left join with the switch statement so ALL of the age ranges will show up, regardless of whether or not there is data. I know I need a table with all of the age ranges, but I am confused.
Here is what I have tried that is currently not working.
Joining the switch statement Age_Range to the table Age Range, where the correlating values in the table are the "Under 20" and "Between 20 and 25" strings in the switch. Not working.
Instead of putting the string values in the table, putting the conditions ([Age]<20, etc). However, this fails because in order to put the conditions in the table, it has to be a text field. There is a data mismatch.
Can someone please let me know if this can be done and how?
Thanks,

Make the crosstab a separate query. Then left join that query to your table of item in #1 ("Under 20" and "Between 20 and 25").

Related

Update query just showing zero values when there exists non-zero values. (ACCESS)

I have been struggling with this for hours. I am trying to update all values that have the same 'SHORT#'. If the 'SHORT#' is in 017_PolWpart2 I want this to be the value that updates the corresponding 'SHORT#' in 017_WithdrawalsYTD_changelater. This update query is just displaying zeroes, but these values are in fact non-zero.
So say 017_WithdrawalsYTD_changelater looks like this:
SHORT# WithdrawalsYTD
1 0
2 0
3 0
4 0
5 0
and 017_PolWpart2 looks like this:
SHORT# Sum_MTD_AGG
3 50
5 12
I want this:
SHORT# WithdrawalsYTD
1 0
2 0
3 50
4 0
5 12
But I get this:
SHORT# WithdrawalsYTD
1 0
2 0
3 0
4 0
5 0
I have attached the SQL for the Query below.
Thanks!
UPDATE 017_WithdrawalsYTD_changelater
INNER JOIN 017b_PolWpart2 ON [017_WithdrawalsYTD_changelater].[SHORT#] =
[017b_PolWpart2].[SHORT#]
SET [017_WithdrawalsYTD_changelater].WithdrawalsYTD = [017b_PolWpart2].[Sum_MTD_AGG];
EDIT:
As I must aggregate on the fly, I have tried to do so. Still getting all kinds off errors. Note the table 17a_PolicyWithdrawalMatch is of the form:
SHORT# MTG_AGG WithdrawalPeriod PolDurY
1 3 1 1
1 5 1 0
2 2 1 1
2 22 1 1
So I aggregate:
SHORT# MTG_AGG
1 3
2 24
And put these aggregated values in 017_WithdrawalsYTD_changelater.
I tried to this like so:
SELECT [017a_PolicyWithdrawalMatch].[SHORT#], Sum([017a_PolicyWithdrawalMatch].MTD_AGG) AS Sum_MTD_AGG
WHERE ((([017a_PolicyWithdrawalMatch].WithdrawalPeriod)=[017a_PolicyWithdrawalMatch].[PolDurY]))
GROUP BY [017a_PolicyWithdrawalMatch].[SHORT#]
UPDATE 017_WithdrawalsYTD_changelater INNER JOIN 017a_PolicyWithdrawalMatch ON [017_WithdrawalsYTD_changelater].[SHORT#] = [017a_PolicyWithdrawalMatch].[SHORT#] SET 017_WithdrawalsYTD_changelater.WithdrawalsYTD =Sum_MTD_AGG;
I am getting no luck... I get told SELECT statement is using a reserved word... :(
Consider heeding #June7's comments to avoid the use of saving aggregate data in a table as it redundantly uses storage resources since such data can be easily queried in real time. Plus, such aggregate values immediately become historical figures since it is saved inside a static table.
In MS Access, update queries must be sourced from updateable objects of which aggregate queries are not, being read-only types. Hence, they cannot be used in UPDATE statements.
However, if you really, really, really need to store aggregate data, consider using domain functions such as DSUM inside the UPDATE. Below assumes SHORT# is a string column.
UPDATE [017_WithdrawalsYTD_changelater] c
SET c.WithdrawalsYTD = DSUM("MTD_AGG", "[017a_PolicyWithdrawalMatch]",
"[SHORT#] = '" & c.[SHORT#] & "' AND WithdrawalPeriod = [PolDurY]")
Nonetheless, the aggregate value can be queried and refreshed to current values as needed. Also, notice the use of table aliases to reduce length of long table names:
SELECT m.[SHORT#], SUM(m.MTD_AGG) AS Sum_MTD_AGG
FROM [017a_PolicyWithdrawalMatch] m
WHERE m.WithdrawalPeriod = m.[PolDurY]
GROUP BY m.[SHORT#]

My sql statement results in zero

SELECT COUNT (Age) AS TwentyToTwentyNineYearOlds
FROM [Copy Of SurveyData]
WHERE Age = 20-29 AND TravelLength = '2+ weeks';
This is my sql statement. I was looking for twenty to twenty-nine-year-olds that were interested in going on a trip for more than 2 weeks. In the database that I am using the actual data is 2+ weeks, I am not looking for Weeks > 2. Every time I run this I get 0. Please tell me what I am doing wrong. I have checked using the database filters and there should be 2 showing up instead of zero. I am using Microsoft Access database. The data for age is called 20-29.
I have fixed this by adding quotations around 20-29.
Your expression Age = 20-29 results in this expression: Age = -9. MS Access makes an arithmetic calculation and as a result you are searching for people aged -9 years. What you need to do instead is this:
SELECT COUNT (Age) AS TwentyToTwentyNineYearOlds
FROM [Copy Of SurveyData]
WHERE Age >= 20 and Age <=29 AND TravelLength = '2+ weeks';
Or use the BETWEEN operator:
SELECT COUNT (Age) AS TwentyToTwentyNineYearOlds
FROM [Copy Of SurveyData]
WHERE Age BETWEEN 20 and 29 AND TravelLength = '2+ weeks';
So I think you probably should build your query in steps. I assume you're using the query design view and not actually composing an sql statement manually.
First I would do a basic select query, not a count, and with just 1 criteria - not multiple. Sanity check your result and go from there.
www.CahabaData.com

Solution for SQL conditional query

I've been tasked with coming up with a solution for a problem that was found this morning. I have a query that I need to do some math with. I have three pertinent columns.
SELECT lQ.[QUANTITY], lQ.[FORM_FACTOR_ID], oQ.[INDIVIDUAL_PACKAGING]
FROM [dbo].[AOF_ORDER_LINE_QUEUE] as lQ
LEFT JOIN [dbo].[AOF_ORDER_QUEUE] AS oQ
ON lQ.[SALES_ORDER_NUMBER] = oQ.[SALES_ORDER_NUMBER]
I can see myself doing this in a loop easily in languages I know best. It doesn't seem that looping is a good thing to do in SQL based on some preliminary research so I am reaching out for suggestions.
I need to output a total value which is a conditional sum of lQ.[QUANTITY]. The condition is if oQ.[FORM_FACTOR_ID] is equal to 1 then the output for that particular row is equal to the value of lQ.[QUANTITY]. If oQ.[FORM_FACTOR_ID] is equal to 2 then if oQ.[INDIVIDUAL_PACKAGING] is true, then the output of that particular row in the query is equal to lQ.[QUANTITY]. If the value is false, then the output of that particular row in the query is divided by 2. The final output needs to be a single integer.
QUANTITY FORM_FACTOR_ID INDIVIDUAL_PACKAGING
4 2 1
5 1 1
I would need a query that outputs the value 7 for the above table.
QUANTITY FORM_FACTOR_ID INDIVIDUAL_PACKAGING
4 2 0
5 2 0
That same query needs to output 5 for the above table.
What would be the best way to go about doing this?
If I understand the question correctly, you just want conditional aggregation -- a CASE as an argument to SUM().
If I follow the logic, it would look like:
SELECT SUM(CASE WHEN oq.FORM_FACTOR_ID = 1 THEN lQ.QUANTITY
WHEN oQ.FORM_FACTOR_ID = 2 AND oQ.INDIVIDUAL_PACKAGING = 1 THEN lQ.QUANTITY
WHEN oQ.FORM_FACTOR_ID = 2 AND oQ.INDIVIDUAL_PACKAGING = 0 THEN lQ.QUANTITY / 2
END)
FROM [dbo].[AOF_ORDER_LINE_QUEUE] lQ LEFT JOIN
[dbo].[AOF_ORDER_QUEUE] oQ
ON lQ.[SALES_ORDER_NUMBER] = oQ.[SALES_ORDER_NUMBER];

what's the difference between SQL's

I work with Databases not extensively but to the point where I can write Selects, update's ,small joins etc..
I can get my work done with my current knowledge. I have encountered some difficulty while trying to complete a task, I got the task completed but would like to understand why some of the SQL's that I have written in process did not work.
Task at hand: I have a table "TESTTABLE" that has 5 columns and the 6th is the sum of these 5 columns.
Currently table looks like below:
ID NAME SUB1 SUB2 SUB3 SUB4 SUB5 TOTAL
1 VA 10 20 30 40 50
2 MI 20 40 60 80 10
3 NC 10 30 50 70 90
4 SC 10 20 30 40 50
5 WA 20 40 60 80 15
the last column 'Total' is currently empty.
Now,I need to update the total column in the table with the sum(sub1+sub2=sub3+sub4+sub5).
In this process I have written the following SQL's and it did work, would like to understand the difference.
Attempt1:
UPDATE TESTTABLE T
SET Total =
SELECT (sub1+sub2+sub3+sub4+sub5)
FROM TESTTABLE TB
WHERE T.ID = TB.ID);
Error encountered:--ERROR: (2) This form of correlated query is not supported - consider rewriting;
Attempt2:
CREATE TABLE TEMP_TESTTABLE AS( SELECT ID, SUM(sub1+sub2+sub3+sub4+sub5) AS SUB_TOTAL FROM TESTTABLE )
UPDATE TESTTABLE A
SET TOTAL =
(SELECT SUB_TOTAL
FROM TEMP_TESTTABLE B
WHERE B.ID=A.ID);
ERROR encountered: ERROR: (2) This form of correlated query is not supported - consider rewriting
Attempt3:
UPDATE TESTTABLE
SET TOTAL = SUM(sub1+sub2+sub3+sub4+sub5);
ERROR encountered: ERROR: Aggregate functions not allowed in the set list of an UPDATE statement
Attempt4- Successful one;
UPDATE TESTTABLE A
SET TOTAL = B.SUB_TOTAL FROM TEMP_TESTTABLE B
WHERE A.ID=B.ID
Attempt 4 worked for me by using the temp table created in attempt2 [TEMP_TESTTABLE].
I need some detail explanation, and appreciate if anyone can provide me and let me know how my attempt4 is different than 1,2,3.
Help is greatly appreciated.
Thanks,
Attempt1 failed because subqueries should be enclosed in parentheses.
UPDATE TESTTABLE T
SET Total =
(SELECT (sub1+sub2+sub3+sub4+sub5)
FROM TESTTABLE TB
WHERE T.ID = TB.ID);
Attempt2 failed because SUM() function is aggregate function, to sum values from multiple rows, not to sum values from multiple columns in one row.
You should redefine the column as a computed column, like this
Alter table TESTTABLE
add column Total as sub1+sub2+sub3+sub4+sub5
This is the cannonical Soluion.
UPDATE
TESTTABLE
SET
Total = (sub1+sub2+sub3+sub4+sub5)
The reason the others failed is that you where doing subselects that returned multiple rows. You didn't tell the UPDATE how the different rows mapped from the select to the UPDATE.
In this version you are making it simple - one table - on each row set a value on that row based on the data in that row.
In your final version you're doing the same but in a redundant way (extra join that does nothing).

New to SQL, need help with query

I have a database table of my own that I am trying to construct a query for that seems simple enough, but I feel like I am messing up somewhere because the results are not what they should be.
I basically have a table that is like the following:
Table: Data
Columns:
Row ID Profile Import ID Field ID Product
1 5 Null 5 60 Can
2 0 Null 5 65 Hat
3 0 Null 5 70 Box
4 6 Null 6 60 Fish
I basically want to take the word "Hat" in row 2 and place it into the "Profile" column of row 1, replacing the null value there. I am doing this for multiple rows.
In the case of the multiple rows I want to take the "Profile" column and make it equal to the "Product" column. I only want this to happen in the rows where the "ID" value matches the "Import ID", and where the "Field ID" is 65 specifically. In the example above the "ID" 5 matches the "Import ID" 5, so I want to take the "Product" value "Hat" where the "Field ID" is 65, and place that value into the "Profile" column where the ID is 5. My table has over 9000 rows and 600 would have to be changed in this way, with various ID's needing various products inserted.
The result I would like would be:
Row ID Profile Import ID Field ID Product
1 5 Hat 5 60 Can
2 0 Null 5 65 Hat
3 0 Null 5 70 Box
4 6 Null 6 60 Fish
I pray that makes sense...
My query was this
UPDATE 'Data'
SET 'Profile'='Product'
WHERE 'ID'='Import ID' AND 'Field ID'=65;
I have also tried a subquery
UPDATE 'Data'
SET 'Profile'= (SELECT 'Product' FROM Data WHERE 'Field ID'=65)
WHERE 'ID'='Import ID';
This did not work and I am just wondering if there is some logic I missing. Thank you to anyone who can help, I have been up for a bit trying to understand this...
You need to join the data; something like:
UPDATE d1
SET d1.Profile = d2.Product
FROM [Data] d1 -- dest
INNER JOIN [DATA] d2 -- source
ON d2.[Import ID] = d1.[ID] AND d2.[Field ID] = 65
(note swapped 2 columns...)
A couple thing to keep in mind when learning sql:
it isnt a good idea to have spaces in column names. although they might be easier to read, it makes your queries more difficult. most databases dont allow them at all, and those that do have different ways to specify the columns in queries.
to work around your problem, perhaps you should try to enclose the column name in backticks (`), or in square brackets ([ ]).
in any case, instead of a space, please consider an underscore.
with that in mind you should also remember that not to put column names in quotes. something like
SELECT 'Product' FROM Data WHERE 'Field ID'=65
would not work for two reasons:
a. Selecting quoted text will return that quoted text. so were the where clause to return two rows, you would get the text 'Product' returned twice.
b. here your where clause is comparing the text 'Field ID' with the number 65, which would always be false.
hope that helps