MS Access 2007: Using SQL to Transpose rows to columns - sql

SQL newbie here. I have table setup as the following (my apologies for the poor formatting):
Cycle ID....UBCI....chemo_cycle....csf....rsn_no_csf
57.............18001...1......................N.......N 58.............18001...2......................N.......N59.............22002...1......................Y........null
I'd like to convert it into the following format:
UBCI....chemo_cycle1....chemo_cycle2....csf1....csf2....rsn_no_csf1....rsn_no_csf2 18001...1.........................2.........................N........N........N.....................N22002...1.........................null......................Y........null.....null..................null
There can be up to 26 chemo_cycles per UBCI. I tried some of the other suggestions, but wasn't familiar enough with SQL to work out some of the finer details. Again, apologies for the formatting. Any help would be appreciated.
Thank you!
-Omar

The only way I can see to do this conveniently in Access is with four queries. I do not think you can use crosstab queries as subqueries, so:
Query 1: cc
TRANSFORM First(TableQ.chemo_cycle) AS FirstOfchemo_cycle
SELECT TableQ.UBCI
FROM TableQ
GROUP BY TableQ.UBCI
PIVOT "CC " & [chemo_cycle];
Query 2: csf
TRANSFORM First(TableQ.csf) AS FirstOfcsf
SELECT TableQ.UBCI
FROM TableQ
GROUP BY TableQ.UBCI
PIVOT "csf " & [chemo_cycle];
Query 3: rsn
TRANSFORM First(TableQ.rsn_no_csf) AS FirstOfrsn_no_csf
SELECT TableQ.UBCI
FROM TableQ
GROUP BY TableQ.UBCI
PIVOT "rsn " & [chemo_cycle];
Final query:
The columns [cc 1] to [cc 26] will show in the design window, and can be added, here they are indicated by <...>
SELECT CC.UBCI,
CC.[CC 1],
CC.[CC 2],
<...>
csf.[csf 1],
csf.[csf 2],
<...>
rsn.[rsn 1],
rsn.[rsn 2]
<...>
FROM (CC INNER JOIN csf
ON CC.UBCI = csf.UBCI)
INNER JOIN rsn
ON csf.UBCI = rsn.UBCI;

Related

Can Someone help me write a query to determine which team lost a match AND a separate query to count each teams losses

I have tried the following code.
SELECT (Team 1) OR ( Team 2) AS[Losser], Winner
FROM MatchesTbl
WHERE (WINNER NOT LIKE (Team 1))
I have attached an image of the table I am working with. I am working in Microsoft access.
I am still very new to programming and I am trying to do this for a school project.
If you use MS Access you can use the IIF function to get the first result
SELECT T.Team1, T.Team2, T.Winner, IIf([Team1]=[Winner],[Team2],[Team1]) AS Loser
FROM tblMatches AS T;
Please note that I modified your orignal table name and field names a little bit.
In MS Access you can save that query and based on the saved query (I saved it as qryLoser) you can get your second result
SELECT qryLoser.Loser, Count(qryLoser.Loser) AS CountOfLoser
FROM qryLoser
GROUP BY qryLoser.Loser;
Here is the original query -- as you an see I left some extra columns here (to make it clearer and you might want to use this for something else)?
SELECT Loser, COUNT(*)
FROM (
SELECT MatchID, [Match Date], Tournamer, [Team 1], [Team 2], Winner,
SWITCH([Team 1] = Winner,[Team 2],
[Team 2] = Winner,[Team 1],
true,'Unknown Loser') AS Loser
FROM MatchesTbl
) X
GROUP BY Loser
Here is the cleaned up answer:
SELECT Loser, COUNT(*)
FROM (
SELECT
SWITCH([Team 1] = Winner,[Team 2],
[Team 2] = Winner,[Team 1],
true,'Unknown Loser') AS Loser
FROM MatchesTbl
) X
GROUP BY Loser
also note, that the answer to your first question in the inner query and the answer to the second question is the outer query

COUNT Clicks/Opens for Engagement Scoring

I am a bit rusty on SQL so any assistance is appreciated. I am also referencing my SQL textbook but I thought I would try this out.
I am developing a lead scoring model starting with engagement scoring. I created a data extension to house the results and used the following query to populate:
SELECT a.[opportunityid],
a.[first name],
a.[last name],
a.[anticipatedentryterm],
a.[funnelstage],
a.[programofinterest],
a.[opportunitystage],
a.[opportunitystatus],
a.[createdon],
a.[ownerfirstname],
a.[ownerlastname],
a.[f or j visa student],
a.[donotbulkemail],
a.[statecode],
Count(DISTINCT c.[subscriberkey]) AS 'Clicks',
Count(DISTINCT b.[subscriberkey]) AS 'Opens',
Count(DISTINCT b.[subscriberkey]) * 1.5 +
Count(DISTINCT c.[subscriberkey]) * 3 AS 'Probability'
FROM [ug_all_time_joined] a
INNER JOIN [open] b
ON a.[opportunityid] = b.[subscriberkey]
INNER JOIN [click] c
ON a.[opportunityid] = c.[subscriberkey]
GROUP BY a.[opportunityid],
a.[first name],
a.[last name],
a.[anticipatedentryterm],
a.[funnelstage],
a.[programofinterest],
a.[opportunitystage],
a.[opportunitystatus],
a.[createdon],
a.[ownerfirstname],
a.[ownerlastname],
a.[f or j visa student],
a.[donotbulkemail],
a.[statecode]
Something is wrong with my COUNT functions, the query populates the same value in both Clicks and Opens and I don't think it's accurate. The result I am aiming for is how many times a subscriber id appears (which would correspond with the individual clicks/opens, each row is a 1 action).
Thank you!
Why is that surprising?
You have two joins that if you take to their logical conclusion imply that
b.[SubscriberKey] = c.[SubscriberKey]
Hence, counting distinct values will be the same.
You have not provide sample data or desired results. I can speculate, though, that you intend LEFT JOINs so you get some values in one table that are not matched in the other.
When you do an inner join, between a and b, your data is filtered when you join a and c, which will give you incorrect results. having no view of your data and no background of your tables, this is the best guess i have

SUM and multiplying on calculated fields

I have a piece of script which is pulling through the desired figures fine. Now I need to multiply the figure given by another calculated field (I shall call field x, which is a case statement with 9 'When Statements') then multiply that by 0.74.
I can not get this to work at all... any ideas... script below
Case
when Left([dbo].[Table1].FIELD 1,3) = 'NEW' and [Field 2] = 'Live'
Then
(SELECT distinct[dbo].[Table2].[Field a]
FROM [MY_DATABASE].[dbo].[Table2]
right Join [dbo].[Table 3]
on ([dbo].[Table2].[Field b]=[dbo].[Table 3].[Field 1])
Where [dbo].[Table2].[Field c] =
(Select
[dbo].[Table 3].[Field1]
From [dbo].[Table 3]
Where [dbo].[Table 3].[Field4] = #parameter
and [Field5] = '7')
and [dbo].[Table2].[Field D]= #Parameter
and [dbo].[Table2].[Field E]= '07')
ELSE 0
END
As [Named Field]
One option here would be common table expressions.
I'd suggest wrapping your select in a cte, the selecting from it and performing any further calculations at the bottom level.
;with cte as (
your original select query
)
select *
, [named field] * [field x] as [calculated answer]
from cte
This saves you having to make the calculations over and over again. There are performance concerns around cte's but they can help in these situations. I'd test on your data and see how much of a hit you take.

Questsion about using HAVING in ACCESS SQL

I wanted to get clarity on how the HAVING component in an SQL statement works, particularly with a SQL statement that has multiple joins. Consider the following SQL select statement:
SELECT
p.id,
p.first_name as [First Name],
p.last_name as [Last Name]
FROM
( [tbl_person] as p
INNER JOIN [tbl_person_languages] as pl
ON [p].[id] = [pl].[person_id])
INNER JOIN [tbl_person_crossCuttingSkills] As ccp
ON [p].[id] = [ccp].[person_id]
WHERE
cint(pl.language_id) in (12,14) AND
cint(ccp.skill_id) in (55)
GROUP BY
p.id,
p.first_name,
p.last_name
HAVING
count(pl.language_id) =2 AND
count(ccp.skill_id) = 1
I want to pull out records, from tbl_person, where a record has all of the WHERE requirements. For example: I want to select all users where they speak a languages Italian (with ID 12) and Spanish (ID 15) AND have a skill of cooking (55). They need to have all requirements, not just one or more. I was under the assumption this is where you would use GROUP BY and HAVING. With the HAVING:
count(pl.language_id) =2
I use count = 2 because there are two options in the language WHERE clause (12 and 14)
And I use
count(ccp.skill_id) = 1
Because there is one value in the WHERE clause (55).
Is this the correct way to be doing this? For some reason, this returns no records (I have one record in my DB of a person who fits these requirements exactly). But, if I change my HAVING to:
count(pl.language_id) =2 AND
count(ccp.skill_id) = 2
It works fine. Why is this? Are my assumptions of how this works incorrect or is there something else going on?
Remember what count() does . . . it counts non-NULL values. So, you are counting two non-NULL values then the counts are the same.
In most dialects of SQL, you can fix this by doing:
HAVING count(distinct pl.language_id) = 2 AND count(distinct ccp.skill_id) = 1
But that doesn't work in MS Access, because MS Access does not support COUNT(DISTINCT).
So, you can be more verbose. In your case:
HAVING SUM(iif(cint(pl.language_id) = 12, 1, 0)) > 0 AND
SUM(iif(cint(pl.language_id) = 14, 1, 0)) > 0 AND
SUM(iif(cint(ccp.skill_id) = 55, 1, 0)) > 0
I'm sorry this HAVING clause is not simpler. You could switch to another database (such as SQL Server Express) that more closely aligns with ANSI functionality.

SQL LEFT JOIN not working in MS Access

The following SQL query returns no data for the LEFT JOIN in MS Access.
SELECT * FROM
(
SELECT Operation_Part.PPC,
Operation_Part.TargetOperationsPerHour as JPH,
Operation_Part.Misc1 as [JPh Alt 1],
STR(Operation_Part.SeqNr) as Sequence,
Operation_Part.idPart,
Operation_Part.idOperationPart,
Operation.OperationType as Operation,
tblOperationType.OperationType as [Operation Type]
FROM tblOperationType
RIGHT JOIN (Operation INNER JOIN Operation_Part ON Operation.idOperation = Operation_Part.idOperation)
ON tblOperationType.idOpType = Operation.OperationTID
WHERE Operation_Part.VsbLDq = 0
AND Operation_Part.idPart <> 0 AND Operation_Part.idPart = 1271)
AS [AA]
LEFT JOIN (SELECT Sum([Cptotal]) AS DownTime,
TransactionDetail.idPart,
STR(TransactionDetail.seq_number) as Sequence
FROM ([Transaction] INNER JOIN TransactionDetail ON [Transaction].idTransaction = TransactionDetail.idTransaction)
WHERE [Transaction].idTransactionType=29
AND TransactionDetail.WorkOrderNumber = 'PR23144'
GROUP BY TransactionDetail.idPart, STR(TransactionDetail.seq_number))
AS [EE]
ON AA.idPart = EE.idPart AND EE.Sequence=AA.Sequence
In SQL Server the query does return the downtime value of 1.08 as required (see pics below).
First select returns:
Second select returns:
MS Access result:
SQL server result:
How do I make it work in MS Access?
This is only a guess, but it may well have something to do with the nulls in the applicable columns of the rows you dont really want.
Suggest you change
SELECT Sum([Cptotal]) AS DownTime,
to
SELECT Sum(IIf(IsNull([CpTotal]), 0, [CpTotal])) AS DownTime
In Access I always use CStr(...) instead of Str(...)
Aside from this, painful though it may be, I'd suggest turning the left-joined component into a separate query, or if you dont use queries, building a temporary table with this data which is then left joined into the original query.