Comparing row based on contents to another tables rows in Access SQL - sql

Hi I'm working on a project and for time constraint reasons I need to keep working in Access which may be the root of all my problems but maybe there's hope.
I have a database that includes a table ANSWERS filled with input for users "wants" there are multiple columns which each correspond to an answer to a different question asking if they, Don't Care, Want, or Need something.
EG: Answers:
Bacon | Ham | Sausage
________________________________
1 0 0 2
2 2 1 0
3 0 2 0
4 1 1 1
(0 = Don't Care, 1 = Want, 2 = Need)
I want to compare a row from table Answers to the Available table.
EG: Available:
Bacon | Ham | Sausage
________________________________
1 0 1 0
2 0 0 0
3 1 1 1
4 1 1 0
(0 = Unavailable, 1 = Available)
So I would want to compare row 1 from Answers to Available so because row 1 includes sausage=2 then I would want to receive row 3 from Available because sausage=1.
I'd be happy receiving the entire row, or the row ID and a "1" for the rows being a match.
Ultimately I'd need to do this for all each of the rows in Answers.
Any ideas are appreciated, I was thinking using Intersect might work but since that doesn't work in access. I've also considered joining the tables, I could also change data variables or formats if necessary.
Thanks very much
Edit: Don't Care was previously Don't Want. Changed for clarity.

Give this a try:
SELECT tblAnswers.UserID, IIf([tblAnswers].[bacon]>0 And [tblMenus].[Bacon]<>0,[MenuID],Null) AS BaconMenu, IIf([tblAnswers].[Ham]>0 And [tblMenus].[Ham]<>0,[MenuID],Null) AS HamMenu, IIf([tblAnswers].[Sausage]>0 And [tblMenus].[Sausage]<>0,[MenuID],Null) AS SausageMenu
FROM tblAnswers, tblMenus
WHERE (((IIf([tblAnswers].[bacon]>0 And [tblMenus].[Bacon]<>0,[MenuID],Null)) Is Not Null)) OR (((IIf([tblAnswers].[Ham]>0 And [tblMenus].[Ham]<>0,[MenuID],Null)) Is Not Null)) OR (((IIf([tblAnswers].[Sausage]>0 And [tblMenus].[Sausage]<>0,[MenuID],Null)) Is Not Null));
Just paste that into a SQL view make Query window (After changing the table and column names to match yours) You will obviously need to tweak it as reality needs, but it does what you asked for with the data provided.

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#]

Converting Column Headers to Row elements

I have 2 tables I am combining and that works but I think I designed the second table wrong as I have a column for each item of what really is a multiple choice question. The query is this:
select Count(n.ID) as MemCount, u.Pay1Click, u.PayMailCC, u.PayMailCheck, u.PayPhoneACH, u.PayPhoneCC, u.PayWuFoo
from name as n inner join
UD_Demo_ORG as u on n.ID = u.ID
where n.MEMBER_TYPE like 'ORG_%' and n.CATEGORY not like '%_2' and
(u.Pay1Click = '1' or u.PayMailCC = '1' or u.PayMailCheck = '1' or u.PayPhoneACH = '1' or u.PayPhoneCC = '1' or u.PayWuFoo = '1')
group by u.Pay1Click, u.PayMailCC, u.PayMailCheck, u.PayPhoneACH, u.PayPhoneCC, u.PayWuFoo
The results come up like this:
Count Pay1Click PayMailCC PayMailCheck PayPhoneACH PayPhoneCC PayWuFoo
8 0 0 0 0 0 1
25 0 0 0 0 1 0
8 0 0 0 1 0 0
99 0 0 1 0 0 0
11 0 1 0 0 0 0
So the question is, how can I get this to 2 columns, Count and then the headers of the next 6 headers so the results look like this:
Count PaymentType
8 PayWuFoo
25 PayPhoneCC
8 PayPhoneACH
99 PayMailCheck
11 PayMailCC
Thanks.
Try this one
Select Count,
CASE WHEN Pay1Click=1 THEN 'Pay1Click'
PayMailCC=1 THEN ' PayMailCC'
PayMailCheck=1 THEN 'PayMailCheck'
PayPhoneACH=1 THEN 'PayPhoneACH'
PayPhoneCC=1 THEN 'PayPhoneCC'
PayWuFoo=1 THEN 'PayWuFoo'
END as PaymentType
FROM ......
I think indeed you made a mistake in the structure of the second table. Instead of creating a row for each multiple choice question, i would suggest transforming all those columns to a 'answer' column, so you would have the actual name of the alternative as the record in that column.
But for this, you have to change the structure of your tables, and change the way the table is populated. you should get the name of the alternative checked and put it into your table.
More on this, you could care for repetitive data in your table, so writing over and over again the same string could make your table grow larger.
if there are other things implied to the answer, other informations in the UD_Demo_ORG table, then you can normalize the table, creating a payment_dimension table or something like this, give your alternatives an ID such as
ID PaymentType OtherInfo(description, etc)...
1 PayWuFoo ...
2 PayPhoneCC ...
3 PayPhoneACH ...
4 PayMailCheck ...
5 PayMailCC ...
This is called a dimension table, and then in your records, you would have the ID of the payment type, and not the information you don't need.
So instead of a big result set, maybe you could simplify by much your query and have just
Count PaymentId
8 1
25 2
8 3
99 4
11 5
as a result set. it would make the query faster too, and if you need other information, you can then join the table and get it.
BUT if the only field you would have is the name, perhaps you could use the paymentType as the "id" in this case... just consider it. It is scalable if you separate to a dimension table.
Some references for further reading:
http://beginnersbook.com/2015/05/normalization-in-dbms/ "Normalization in DBMS"
http://searchdatamanagement.techtarget.com/answer/What-are-the-differences-between-fact-tables-and-dimension-tables-in-star-schemas "Differences between fact tables and dimensions tables"

SQL ORDER BY 0 (int) needs to be first

I am attempting to sort an integer field in ASC order, but it is automatically putting the "0" value near the bottom (just above NULL values).
I am using SQL Server 2005. I think my DBMS is outdated, because I attempted to use NULLS FIRST, and it was not recognized.
*Edited to show better query (thanks for the quick feedback)
What I want to see:
PriSortOrder/CommunityName
0/Towson
1/Atlanta
2/Baltimore
NULL
What I see:
PriSortOrder/CommunityName
1/Atlanta
2/Baltimore
0/Towson
NULL
Query:
SELECT PriSortOrder, CommunityName
FROM Communities
WHERE InCatalog=1
ORDER BY PriSortOrder
Until you show the PrioritySortOrder value as well as the Community value, you can't say that the data is in the right (or wrong) order. For example, if the data is:
Community PrioritySortOrder
0 5
1 0
2 3
NULL 6
You will get the output:
1
2
0
NULL
If the data is:
Community PrioritySortOrder
0 0
1 1
2 2
NULL 3
then you will get the result:
0
1
2
NULL
You can fix your SQL by (adding a FROM table clause and) ordering by Community instead of PrioritySortOrder (though whether the NULL comes first or last depends on your DBMS).

T-SQL 2008 INSERT dummy row WHEN condition is met

**Schema & Dataset**
id version payment name
1 1 10 Rich
2 1 0 David
3 1 10 Marc
4 1 10 Jess
5 1 0 Steff
1 2 10 Rich
2 2 0 David
3 2 10 Marc
4 2 10 Jess
5 2 0 Steff
2 3 0 David
3 3 10 Marc
4 3 10 Jess
http://sqlfiddle.com/#!3/1c457/18 - Contains my schema and the dataset I'm working with.
Background
The data above is the final set after a stored proc has done it's processing so everything above is in one table and unfortunately I can't change it.
I need to identify in the dataset where a person has been deleted with a payment total greater than 0 in previous versions and insert a dummy row with a payment of 0. So in the above example, Rich has been deleted in version 3 with a payment total of 10 on previous versions. I need to first identify where this has happened in all instances and insert a dummy row with a 0 payment for that version. Steff has also been deleted on version 3 but she hasn't had a payment over 0 on previous versions so a dummy row is not needed for her.
Tried so far -
So I looked at pinal dave's example here and I can look back to the previous row which is great so it's a step in the right direction. I'm not sure however of how to go about achieving the above requirement. I've been toying with the idea of a case statement but I'm not certain that would be the best way to go about it. I'm really struggling with this one and would appreciate some advice on how to tackle it.
You can do this by generating all possible combinations of names and versions. Then filter out the ones you don't want according to the pay conditions:
select n.name, v.version, coalesce(de.payment, 0) as payment
from (select name, max(payment) as maxpay from dataextract group by name) n cross join
(select distinct version from dataextract) v left outer join
dataextract de
on de.name = n.name and de.version = v.version
where de.name is not null or n.maxpay > 0;
Here is a SQL Fiddle.

sum(coalesce()) returns 1 less then true value

I have a table that has 2 columns that keep home and away team id's then 2 columns that keep home and away points, I want to query the database so that it returns the total of points a specific team has earned. Here is my code and it returns a answer that is 1 less then the actual value and it does that for each team I try, why would this be?
select sum(coalesce(hpoints,apoints)) Points
from plays_a
where (tawayid='2013T1' or thomeid='2013T1')
Thank you
Will try this other query.
Edit-
Didn't seem to work it returned 5 for this data.
HPOINTS THOMEID APOINTS TAWAYID
---------- ---------- ---------- ----------
1.5 2013T5 2.5 2013T6
3 2013T4 1 2013T1
2 2013T6 2 2013T3
2 2013T2 2 2013T5
3 2013T6 1 2013T1
3 2013T2 1 2013T3
2.5 2013T4 1.5 2013T5
1 2013T3 3 2013T1
1 2013T4 3 2013T2
3 2013T6 1 2013T5
3 2013T3 1 2013T2
NEVERMIND looks like it was correct will try again with a different team and post back
I think you want this query:
select sum(CASE WHEN thomeid='2013T1' THEN hpoints ELSE apoints END) Points
from plays_a
where (tawayid='2013T1' or thomeid='2013T1')
In your original query, you're always taking the home teams points score, if it's not NULL, even if the team was the away team. That doesn't seem correct. Of course, your table might be completely bizarre and always only filling in the away columns or the home columns in any particular row, but that's not how I'd expect the data to look and doesn't seem to match your description.