Access - retrieving status and date puzzle - sql

In Access 2016, I have the following tables:
Table1
------
| ID | FK_ID | Status_date |Status_ID |
---------------------------------------
| 1 | 11 | d1 | 1 |
| 2 | 11 | d2 | 2 |
| 3 | 22 | d3 | 3 |
| 4 | 22 | d4 | 3 |
LookupTable1
------------
| OBJ_ID | Status |
-------------------
| 1 | A |
| 2 | B |
| 3 | C |
And I would like to produce the following result. This will ultimately be exported to Excel.
xls report
==========
| FK_ID | Status_1_date | Status_2_date | Status_3_date | <-- these will be aliased
=========================================================
| 11 | d1 | d2 | |
| 22 | | | d4 |
The part of the puzzle I'm struggling with is that there seem to be at least these different ways to achieve this a) multiple Access queries b) a single Access query with in-line queries (possible?) c) VBA code d) in SQL Server itself e) other... What's the simplest way to create and maintain this, as the LookupTable1.Status values will change.

Looks like a simple CROSSTAB query:
TRANSFORM Max(Table1.Status_date) AS MaxOfStatus_date
SELECT Table1.FK_ID
FROM Table1
GROUP BY Table1.FK_ID
PIVOT Table1.Status_ID;
If you want the output to show the Status alias values, first JOIN the two tables then use the Status field as column header in CROSSTAB.

Related

How to upend query to a table as new column in Access?

As a follow up to my previous question I wanted to go further with it and do other calculations based on my Diff.
Sample table:
+-------+-------+--------+-------------------+------+------+------+
| ID | RowID | User | Godzina_transakcji| Diff | Diff2| Diff3|
+-------+-------+--------+-------------------+------+------+------+
| 3 | 1 | AAA | 14:23:03 | | | |
| 8 | 2 | AAA | 14:23:57 | | | |
| 11 | 3 | AAA | 14:25:03 | | | |
| 2 | 4 | BBB | 03:37:23 | | | |
| 893 | 5 | BBB | 03:39:21 | | | |
| 5 | 6 | BBB | 05:23:11 | | | |
+-------+-------+---------+------------------+------+------+------+
Working code:
SELECT
tblTemp2.RowID,
tblTemp2.User,
tblTemp2.Godzina_transakcji,
Format(( Select TimeValue(T.Godzina_transakcji)
From tblTemp2 As T
Where tblTemp2.RowID = T.RowID + 1 And tblTemp2.User = T.User ) - TimeValue([Godzina_transakcji]), "hh:nn:ss") As Diff
FROM
tblTemp2;
So I thought the best way will be append my tblTemp with Diff, and here is where it started to hit the fan.
When I tried to change query to "Make table" my Access freezes for up to 10min. When I try to use Update query I get error about "Operation must use an updatable query.".
So my question is: what is best way to do this having in mind that next fields will be simple ifs based on calculated Diff?
For example idea about Diff2 is to check if value of hours in Diff is bigger than 4.
Edit: Hope, now it's more precise and goes along with rules :)

SQL Remove all rows from duplicate rows blocks keeping only one from each block

I have a database table that's supposed to represent the changes in state of an item.
so the columns of this table are : id, state, updatedAt.
I want to do a SQL query to display the changes of states of an item, what I mean by this is when an item passes from one state to another. so a result of a query should look like this.
| id | state | date
| 1 | A | d1
| 2 | B | d2
| 3 | A | d3
| 4 | C | d4
The problem is that the table actually has multiple state columns, so the columns may actually be something like : id, state1, state2, updatedAt.
| id | state 1| state 2| date
| 1 | A | X | d1
| 2 | A | Y | d2
| 3 | B | Y | d3
| 4 | B | Z | d4
Basically I want to query for the history of one specific state column, for example, the result of the query for state 1 columns on the last table should be :
| id | state 1| date
| 1 | A | X | d1
| 3 | B | Y | d3
I hope I made my problem clear.
For this sample data you can use lag() to compare the current state with the previous:
select t.id, t.state1, t.state2, t.date
from (
select *, lag(state1) over (order by date) prevstate1
from tablename
) t
where t.state1 <> t.prevstate1 or t.prevstate1 is null
See the demo.
Results:
| id | state1 | state2 | date |
| --- | ------ | ------ | ---- |
| 1 | A | X | d1 |
| 3 | B | Y | d3 |

db2, roll up unknown number of rows from case statement result

I am trying to write a query where I can concatenate some rows into a single column based on the result of the case statement in DB2 v9.5
The contractId can be a variable number of rows as well.
Given I have the following table structure
Table1
+------------+------------+------+
| ContractId | Reference | Code |
+------------+------------+------+
| 12 | P123456789 | A |
| 12 | A987654321 | B |
| 12 | 9995559971 | C |
| 12 | 3215654778 | D |
| 13 | abcdef | A |
| 15 | asdfa | B |
| 37 | 282jd | B |
| 89 | asdf82 | C |
+------------+------------+------+
I would like to get the output of the result like so
+-------------+-----------------------+------------------------------------+
| ContractId | Reference with Code A | Other References |
+-------------+-----------------------+------------------------------------+
| 12 | P123456789 | A987654321, 9995559971, 3215654778 |
| 13 | abcdef | asdfa, 282jd, asdf82 |
+-------------+-----------------------+------------------------------------+
I've tried queries like
select t1.contract_id,
max(case when t1.code = A then t1.reference end) as "reference with code a",
max(case when t1.code in ('B','C','D') then t1.reference end) as 'other references
from table t1
group by t1.contractId
however, this is still giving me an output like
+-------------+-----------------------+------------------+
| ContractId | Reference with Code A | Other References |
+-------------+-----------------------+------------------+
| 12 | P123456789 | null |
| 12 | null | A987654321 |
| 12 | null | 9995559971 |
| 12 | null | 3215654778 |
+-------------+-----------------------+------------------+
I've also attempted using some of the XML Agg functions but can't seem to get it to format the way I want it too.

Spark dataframe add Missing Values

I have a dataframe of the following format. I want to add empty rows for missing time stamps for each customer.
+-------------+----------+------+----+----+
| Customer_ID | TimeSlot | A1 | A2 | An |
+-------------+----------+------+----+----+
| c1 | 1 | 10.0 | 2 | 3 |
| c1 | 2 | 11 | 2 | 4 |
| c1 | 4 | 12 | 3 | 5 |
| c2 | 2 | 13 | 2 | 7 |
| c2 | 3 | 11 | 2 | 2 |
+-------------+----------+------+----+----+
The resulting table should be of the format
+-------------+----------+------+------+------+
| Customer_ID | TimeSlot | A1 | A2 | An |
+-------------+----------+------+------+------+
| c1 | 1 | 10.0 | 2 | 3 |
| c1 | 2 | 11 | 2 | 4 |
| c1 | 3 | null | null | null |
| c1 | 4 | 12 | 3 | 5 |
| c2 | 1 | null | null | null |
| c2 | 2 | 13 | 2 | 7 |
| c2 | 3 | 11 | 2 | 2 |
| c2 | 4 | null | null | null |
+-------------+----------+------+------+------+
I have 1 Million customers and 360(in the above example only 4 is depicted) Time slots.
I figured out a way to create a Dataframe with 2 columns (Customer_id,Timeslot) with (1 M x 360 rows) and do a Left outer join with the original dataframe.
Is there a better way to do this?
You can express this as a SQL query:
select df.customerid, t.timeslot,
t.A1, t.A2, t.An
from (select distinct customerid from df) c cross join
(select distinct timeslot from df) t left join
df
on df.customerid = c.customerid and df.timeslot = t.timeslot;
Notes:
You should probably put this into another dataframe.
You might have tables with the available customers and/or timeslots. Use those instead of the subqueries.
I think can used the answer of gordon linoff but you can add the following thinsg as you stated that there are millions of customer and you are performing join in them.
use tally table for TimeSlot?? because it might give a better performance.
for more usabllity please refer the following link
http://www.sqlservercentral.com/articles/T-SQL/62867/
and I think you should use partition or row number function to divide you column customerid and select the customers based on some partition value. For example just select the row number values and then cross join with the tally table. it can imporove your performance .

Selecting all rows in a master table and summing columns in multiple detail tables

I have a master table (Project List) along with several sub tables that are joined on one common field (RecNum). I need to get totals for all of the sub tables, by column and am not sure how to do it. This is a sample of the table design. There are more columns in each table (I need to pull * from "Project List") but I'm showing a sampling of the column names and values to get an idea of what to do.
Project List
| RecNum | Project Description |
| 6 | Sample description |
| 7 | Another sample |
WeekA
| RecNum | UserName | Day1Reg | Day1OT | Day2Reg | Day2OT | Day3Reg | Day3OT |
| 6 | JustMe | 1 | 2 | 3 | 4 | 5 | 6 |
| 6 | NotMe | 1 | 2 | 3 | 4 | 5 | 6 |
| 7 | JustMe | | | | | | |
| 7 | NotMe | | | | | | |
WeekB
| RecNum | UserName | Day1Reg | Day1OT | Day2Reg | Day2OT | Day3Reg | Day3OT |
| 6 | JustMe | 7 | 8 | 1 | 2 | 3 | 4 |
| 6 | NotMe | 7 | 8 | 1 | 2 | 3 | 4 |
| 7 | JustMe | | | | | | |
| 7 | NotMe | | | | | | |
So the first query should return the complete totals for both users, like this:
| RecNum | Project Description | sumReg | sumOT |
| 6 | Sample description | 40 | 52 |
| 7 | Another sample | 0 | 0 |
The second query should return the totals for just a specified user, (WHERE UserName = 'JustMe') like this:
| RecNum | Project Description | sumReg | sumOT |
| 6 | Sample description | 20 | 26 |
| 7 | Another sample | 0 | 0 |
Multiple parallel tables with the same structure is usually a sign of poor database design. The data should really be all in one table, with additional columns specifying the week.
You can, however, use union all to bring the data together. The following is an example of a query:
select pl.recNum, pl.ProjectDescription,
sum(Day1Reg + Day2Reg + Day3Reg) as reg,
sum(Day1OT + Day2OT + Day3OT) as ot
from ProjectList pl join
(select * from weekA union all
select * from weekB
) w
on pl.recNum = w.recNum
group by l.recNum, pl.ProjectDescription,;
In practice, you should use select * with union all. You should list the columns out explicitly. You can add appropraite where clauses or conditional aggregation to get the results you want in any particular case.