Issue with PIVOTING two columns at the same time and one includes a datetime column in SQL Server - sql

I have a table used for attendance tracking, so I can track the arrival time of a person and the date in which they have arrived. I'm now trying to get a report based on that data and have created a view for it below. I have used the PIVOT function to split up the dates and it works without the column highlighted in bold below. The only issue is that I'm trying to PIVOT on a second column called DeviceFirstScannedTime which returns a datetime value, once that gets added the original PIVOT query doesn't group correctly.
Using SQL Server 2012
Current Query for PIVOTING
SELECT *
FROM (SELECT [Code] AS [CB Code], [Lastname], [Firstname], CompanyName AS [Company], DeviceScannedDateOnly, [Code], **DeviceFirstScannedTime**
FROM [dbo].[vLDN23_DailyReportForPivot]) AS SourceTable
PIVOT (Count([Code]) FOR DeviceScannedDateOnly IN ([06/02/2023], [07/02/2023])) AS PivotTable;
What it shows without the DeviceFirstScannedTime column added, shows it will pivot on DeviceScannedDateOnly and Split the dates correctly (it groups the two scans in the original source table and pivots them);
CB Code
Lastname
Firstname
Company
06/02/23
07/02/23
WSSPS24HX6
Smith
Bob
Stan
1
1
With the datetime column added I get the data separated;
CB Code
Lastname
Firstname
Company
DeviceFirstScannedTime
06/02/23
07/02/23
WSSPS24HX6
Smith
Bob
Stan
2023-02-06 10:12:0060
1
0
WSSPS24HX6
Smith
Bob
Stan
2023-02-07 13:87:0000
0
1
Data is now split which isn't ideal for reporting..
What I'm trying to do is this
Firstname
Company
06 Scanned time
06/02/23
07 Scanned Time
07/02/23
Bob
Stan
2023-02-06 10:12:0060
1
2023-02-07 13:87:0000
1
I've removed the first couple of columns to make it more readable but essentially I'm trying to PIVOT on two columns and split the table accordingly all into one line.
Is that possible with a datatime column?

Related

Flatten two repeated struct columns and join with one of them being transposed in BigQuery

I need to flatten a table with 2 repeated struct columns in BigQuery. Below is an example:
Column person has type of a repeated struct with fields name and occupation, show is also a repeated struct with fields title and time, so example #1 displays a single row from that table.
person.name
person.occupation
show.title
show.time
John Cena
Wrestler
Raw
Monday Night
Steve Austin
Wrestler
SmackDown
Friday Night
Vince McMahon
Chairman
What I need to do is to flatten column show in a way that every element from that column becomes a row, but also that row would be enriched by all entries from column person as individual columns. Example #2 demonstrates what I mean:
John Cena
Steve Austin
Vince McMahon
title
time
Wrestler
Wrestler
Chairman
Raw
Monday Night
Wrestler
Wrestler
Chairman
SmackDown
Friday Night
I was able to write a query to flatten show column, but I can't quite figure out how to also transpose column person and add it to output. This is what I currently have:
SELECT * EXCEPT (structuredShow),
structuredShow.*
FROM (SELECT * EXCEPT (show),
(SELECT AS STRUCT *
FROM UNNEST(show)) AS structuredShow
FROM `project.dataset.table`);
Could someone please take a look and see whether what I need is even possible with StandardSQL? Thanks!
If I understand correctly:
SELECT p.* (EXCEPT show), s.*
FROM `project.dataset.table` t CROSS JOIN
UNNEST(t.person) p CROSS JOIN
UNNEST(p.show) s

SELECT from 50 columns

I have a table that has many columns around 50 columns that have datetime data that represent steps user takes when he/she do a procedure
SELECT UserID, Intro_Req_DateTime, Intro_Onset_DateTime, Intro_Comp_DateTime, Info_Req_DateTime, Info_Onset_DateTime, Info_Comp_DateTime,
Start_Req_DateTime, Start_Onset_DateTime, Start_Comp_DateTime,
Check_Req_DateTime, Check_Onset_DateTime, Check_Comp_DateTime,
Validate_Req_DateTime, Validate_Onset_DateTime, Validate_Comp_DateTime,
....
FROM MyTable
I want to find the Step the user did after certain datetime
example I want to find user ABC what the first step he did after 2 May 2019 17:25:36
I cannot use case to check this will take ages to code
is there an easier way to do that?
P.S. Thanks for everyone suggested redesigning the database.. not all databases can be redesigned, this database is for one of the big systems we have and it is been used for more than 20 years. redesigning is out of the equation.
You can use CROSS APPLY to unpivot the values. The syntax for UNPIVOT is rather cumbersome.
The actual query text should be rather manageable. No need for complicated CASE statements. Yes, you will have to explicitly list all 50 column names in the query text, you can't avoid that, but it will be only once.
SELECT TOP(1)
A.StepName
,A.dt
FROM
MyTable
CROSS APPLY
(
VALUES
('Intro_Req', Intro_Req_DateTime)
,('Intro_Onset', Intro_Onset_DateTime)
,('Intro_Comp', Intro_Comp_DateTime)
.........
) AS A (StepName, dt)
WHERE
MyTable.UserID = 'ABC'
AND A.dt > '2019-05-02T17:25:36'
ORDER BY dt DESC;
See also How to unpivot columns using CROSS APPLY in SQL Server 2012
The best way is to design your table with your action type and datetime that action was done. Then you can use a simple where clause to find what you want. The table should be like the table below:
ID ActionType ActionDatetime
----------- ----------- -------------------
1492 1 2019-05-13 10:10:10
1494 2 2019-05-13 11:10:10
1496 3 2019-05-13 12:10:10
1498 4 2019-05-13 13:10:10
1500 5 2019-05-13 14:10:10
But in your current solution, you should use UNPIVOT to get what you want. You can find more information in this LINK.

How to select columns of different lengths

I have a table of part numbers along with many of their properties like such:
[Part Number] [Type] [Manager] [Cat. Code] [etc...]
AAA-001 A Dave 123
DDD-008 D Chris 153
BBB-003 B Dave 254
CCC-008 C Dave 153
...
I'm trying to make a list of all the unique values of each property so it looks more like this:
[Type] [Manager] [Cat. Code] [etc...]
A Dave 123
B Chris 153
C 254
D
However whenever I try to do this using SELECT DISTINCT * or the like, it fills up all the columns so that they're the same length as the longest one, filled horizontally according to the original table:
[Type] [Manager] [Cat. Code] [etc...]
A Dave 123
B Dave 254
C Dave 153
D Chris 153
How do I stop this from happening, and just keep unique values of each column, even if they might be different lengths?
I think you've misunderstood what DISTINCT does. It will filter your results so that all rows returned are unique, not each column. Depending which columns are named in your SELECT, you'll get different results. For an example, see http://www.techonthenet.com/sql_server/distinct.php and the section "Example - With Multiple Expressions"
For your case, if you want lists of the unique values in each column, then you'll have to do a separate query on each column, e.g.:
SELECT DISTINCT [Type] FROM [Parts]
SELECT DISTINCT [Manager] FROM [Parts]
...etc
If you then want them side-by-side (as per your sample desired output), you'll just have to copy and paste them into a spreadsheet or something.

oracle - sql query select max from each base

I'm trying to solve this query where i need to find the the top balance at each base. Balance is in one table and bases are in another table.
This is the existing query i have that returns all the results but i need to find a way to limit it to 1 top result per baseID.
SELECT o.names.name t.accounts.bidd.baseID, MAX(t.accounts.balance)
FROM order o, table(c.accounts) t
WHERE t.accounts.acctype = 'verified'
GROUP BY o.names.name, t.accounts.bidd.baseID;
accounts is a nested table.
this is the output
Name accounts.BIDD.baseID MAX(T.accounts.BALANCE)
--------------- ------------------------- ---------------------------
Jerard 010 1251.21
john 012 3122.2
susan 012 3022.2
fin 012 3022.2
dan 010 1751.21
What i want the result to display is calculate the highest balance for each baseID and only display one record for that baseID.
So the output would look only display john for baseID 012 because he has the highest.
Any pointers in the right direction would be fantastic.
I think the problem is cause of the "Name" column. since you have three names mapped to one base id(12), it is considering all three records as unique ones and grouping them individually and not together.
Try to ignore the "Name" column in select query and in the "Group-by" clause.
SELECT t.accounts.bidd.baseID, MAX(t.accounts.balance)
FROM order o, table(c.accounts) t
WHERE t.accounts.acctype = 'verified'
GROUP BY t.accounts.bidd.baseID;

Rows to Dynamic columns in Access

I need a setup in Access where some rows in a table are converted to columns...for example, lets say I have this table:
Team Employee DaysWorked
Sales John 23
Sales Mark 3
Sales James 5
And then through the use of a query/form/something else, I would like the following display:
Team John Mark James
Sales 23 3 5
This conversion of rows to columns would have to be dynamic as a team could have any number of Employees and the Employees could change etc. Could anyone please guide me on the best way to achieve this?
You want to create a CrossTab query. Here's the SQL that you can use.
TRANSFORM SUM(YourTable.DaysWorked) AS DaysWorked
SELECT YourTable.Team
FROM YourTable
GROUP BY YourTable.Team
PIVOT YourTable.Employee
Of course the output is slightly different in that the columns are in alphabetical order.
Team James John Mark
Sales 5 23 3
For more detail see Make summary data easier to read by using a crosstab query at office.microsoft.com