SQL Statement to show columns multiple times - sql

I have a table containing an integer column that represents a work place, an integer column that represents the number of workpieces finished at that workplace and a date column.
I want to create a query that creates rows of the following type
location int | date of Max(workpiece) | max workpieces | Min(Date) | workpieces (Min(Date)) | max(Date) | workpieces (Max(Date))
So i want a row for each location containing the date of the day where the most pieces where finished plus the amount of the pieces, the oldest date and the pieces finished on that day and the newest date plus the number of pieces finished that day.
Do I have to use joins, to join the table with itself 3 times each given one of the criteria and then join on location? Is The GROUP BY Operator involved, which I don't quite get the hang of?
EDIT: Here's some sample data
+-------+-----------+-----------+-------------------+
| id | location | amount | date |
+-------+-----------+-----------+-------------------+
| 1 | 1 | 10 | 01.01.2016 |
| 2 | 2 | 5 | 01.01.2016 |
| 3 | 1 | 6 | 02.01.2016 |
| 4 | 2 | 35 | 02.01.2016 |
| 5 | 1 | 50 | 03.01.2016 |
| 6 | 2 | 20 | 03.01.2016 |
+-------+-----------+-----------+-------------------+
I want my output to look like this:
loc | dateMaxAmount| MaxAmount | MinDate | AmountMinDate | MaxDate | MaxDateAmount
1 | 03.01.2016 | 50 | 01.01.2016| 10 | 03.01.2016| 50
2 | 02.01.2016 | 35 | 01.01.2016| 5 | 03.01.2016| 20
I am using MS Access.

Related

Find Aggregated Data Between Two Dates in Two Tables Where One is Updated Weekly and Other is Updated Hourly

I have data in two different tables, one is updated every week or once in the middle of the week if needed, and the other table is updated every hour or so because it has more data. The first table, can be seen as
agent_id | rank | ranking_date
---------------------------
1 | 1 | 2022-03-21
2 | 2 | 2022-03-21
1 | 4 | 2022-03-14
2 | 3 | 2022-03-14
1 | 2 | 2022-03-10
And the second table contains detailed information on sales.
agent_id | call_id | talk_time | product_sold | amount | call_date
------------------------------------------------------------------
1 | 1 | 13 | 1 | 53 |2022-03-10
1 | 2 | 24 | 2 | 2 |2022-03-10
2 | 3 | 43 | 4 | 11 |2022-03-10
1 | 4 | 31 | - | 0 |2022-03-10
2 | 5 | 12 | - | 0 |2022-03-10
1 | 6 | 11 | - | 0 |2022-03-11
1 | 7 | 35 | 2 | 79 |2022-03-11
2 | 8 | 76 | - | 0 |2022-03-11
1 | 9 | 42 | 1 | 23 |2022-03-11
2 | 10 | 69 | - | 0 |2022-03-11
How can I merge the two tables to get their aggregated information? Remember the ranks change at the beginning of every week, and the sales happen every day. But the rankings can also be changed in the middle of the week if needed. So what I am trying to get is created an aggregated table for understanding the sales by each agent. Something like this
agent_id | rank | ranking_date | total_calls_handled | total_talktime | total_amount
------------------------------------------------------------------------------------
1 | 1 | 2022-03-21 | 100 | 875 | 3000 (this is 3/21 - today)
2 | 2 | 2022-03-21 | 120 | 576 | 3689 (this is 3/21 - today)
1 | 4 | 2022-03-14 | 210 | 246 | 1846 (this is 3/14 - 3/21)
2 | 3 | 2022-03-14 | 169 | 693 | 8562 (this is 3/14 - 3/21)
1 | 2 | 2022-03-10 | 201 | 559 | 1749 (this is 3/7 - 3/10)
So the data is aggregated for each agent from 7-10, 10 - 14, then 14-21. Also, if say, the latest ranking date is 2022-03-21, and today is 2022-03-23, the query returns aggregation until today.
[Edit]: added table and data details
Table and data details:
Rankings table:
agent_id: unique_id of the agent
rank: rank of an agent assigned updated every Monday or if needed
ranking_date: date when agent's ranking was last updated (Automatically every Monday or if needed)
Sales Table:
agent_id: unique_id of the agent
call_id: unique_id for a call
talk_time: duration of the call
product_sold: unique_id of the product sold (- if agent was unsuccessful to sell)
amount: commission earned by the agent (therefore same product_id has different amount) (0 if agent was unsuccessful to sell)
call_date: date when which call was made
[Edit 2]: Here is SQLFiddle.
Here we join where ranking_date and call_date are in the same week. If you make calls sunday you will need to check whether it falls in the same week as you want.
The syntax in the query is for SQL server, as the SQL Fiddle given. You will need to modify the line of the join to
on date_part(w,r.ranking_date) = date_part(w,s.call_date)
which should be compatible with Google Redshift.
select
r.agent_id,
r.rank,
r.ranking_date,
count(s.call_id) TotalCalls,
sum(s.talk_time) TotalTime,
sum(s.amount) TotalAmount
from rankings r
left join sales s
on datename(ww,r.ranking_date)= datename(ww,s.call_date)
group by
r.agent_id,
r.rank,
r.ranking_date
GO
agent_id | rank | ranking_date | TotalCalls | TotalTime | TotalAmount
-------: | ---: | :----------- | ---------: | --------: | ----------:
1 | 1 | 2022-03-21 | 0 | null | null
1 | 2 | 2022-03-10 | 10 | 356 | 168
1 | 4 | 2022-03-14 | 0 | null | null
2 | 2 | 2022-03-21 | 0 | null | null
2 | 3 | 2022-03-14 | 0 | null | null
db<>fiddle here

How to set a SQL statement into other statement to create a view

I'm trying to write a SQL statement that includes another statement, to get from that all a view. I have 1 data Table. this table have 3 rows(see: Table 1). What I'm trying to do is create a view which select all dates one time DISTINCT. now for every selected date row, select all rows where date = date and sum all price.
For example: the Main table
+----+--------------+---------------+------------+
| id | article_name | article_price | date |
+----+--------------+---------------+------------+
| 1 | T-Shirt | 10 | 2020-11-16 |
| 2 | Shoes | 25 | 2020-11-16 |
| 3 | Pullover | 35 | 2020-11-17 |
| 4 | Pants | 10 | 2020-11-18 |
+----+--------------+---------------+------------+
What im expecting is to have 3 rows(because the first 2 rows have the same date)
+------------+-----+
| date | sum |
+------------+-----+
| 2020-11-16 | 35 |
| 2020-11-17 | 35 |
| 2020-11-18 | 10 |
+------------+-----+
I'm having a hard time to think about an "Algorithm" to solve this.
any ideas?
Use group by!
select date, sum(article_price) as sum_article_price
from mytable
group by date

Repeat a Field Value

A data table I'm working in has multiple rows of costs for an item that need to be summed but, one of the values from another field needs to be repeated on that summed row. For example:
+-------------+------+-------------+
| ITEM NUMBER | COST | OTHER VALUE |
+-------------+------+-------------+
| 1 | 10 | -1 |
| 2 | 4 | -1 |
| 1 | -2 | 123 |
| 3 | 3 | -1 |
And lots more...
The results should look like:
+-------------+------+-------------+
| ITEM NUMBER | COST | OTHER VALUE |
+-------------+------+-------------+
| 1 | 8 | 123 |
| 2 | 4 | -1 |
| 3 | 3 | -1 |
I could make a table of item numbers with, "Other values," greater than zero but, am wondering if there's a cooler way.
Thanks for the help!
Simple aggregation should work for your use case:
select item_number, sum(cost) cost, max(other_value) other_value
from mytable
group by item_number

SQL generate unique ID from rolling ID

I've been trying to find an answer to this for the better part of a day with no luck.
I have a SQL table with measurement data for samples and I need a way to assign a unique ID to each sample. Right now each sample has an ID number that rolls over frequently. What I need is a unique ID for each sample. Below is a table with a simplified dataset, as well as an example of a possible UID that would do what I need.
| Row | Time | Meas# | Sample# | UID (Desired) |
| 1 | 09:00 | 1 | 1 | 1 |
| 2 | 09:01 | 2 | 1 | 1 |
| 3 | 09:02 | 3 | 1 | 1 |
| 4 | 09:07 | 1 | 2 | 2 |
| 5 | 09:08 | 2 | 2 | 2 |
| 6 | 09:09 | 3 | 2 | 2 |
| 7 | 09:24 | 1 | 3 | 3 |
| 8 | 09:25 | 2 | 3 | 3 |
| 9 | 09:25 | 3 | 3 | 3 |
| 10 | 09:47 | 1 | 1 | 4 |
| 11 | 09:47 | 2 | 1 | 4 |
| 12 | 09:49 | 3 | 1 | 4 |
My problem is that rows 10-12 have the same Sample# as rows 1-3. I need a way to uniquely identify and group each sample. Having the row number or time of the first measurement on the sample would be good.
One other complication is that the measurement number doesn't always start with 1. It's based on measurement locations, and sometimes it skips location 1 and only has locations 2 and 3.
I am going to speculate that you want a unique number assigned to each sample, where now you have repeats.
If so, you can use lag() and a cumulative sum:
select t.*,
sum(case when prev_sample = sample then 0 else 1 end) over (order by row) as new_sample_number
from (select t.*,
lag(sample) over (order by row) as prev_sample
from t
) t;

How to generate this report?

I'm trying to set up a report based on several tables.
I have a table Actual that looks like this:
+--------+------+
| status | date |
+--------+------+
| 5 | 7/10 |
| 8 | 7/9 |
| 8 | 7/11 |
| 5 | 7/18 |
+--------+------+
Table Targets looks like this:
+--------+-------------+--------+------------+
| status | weekEndDate | target | cumulative |
+--------+-------------+--------+------------+
| 5 | 7/12 | 4 | 45 |
| 5 | 7/19 | 5 | 50 |
| 8 | 7/12 | 4 | 45 |
| 8 | 7/19 | 5 | 50 |
+--------+-------------+--------+------------+
Grouping the Actual records by which Targets.weekEndDate they fall under, I have the following aggregate query GroupActual:
+-------------+------------+--------------+--------+------------+
| weekEndDate | status | weeklyTarget | actual | cumulative |
+-------------+------------+--------------+--------+------------+
| 7/12 | 5 | 4 | 1 | 45 |
| 7/12 | 8 | 4 | 2 | 41 |
| 7/19 | 5 | 5 | 1 | 50 |
| 7/19 | 8 | 4 | | 45 |
+-------------+------------+--------------+--------+------------+
I'm trying to create this report:
+--------+------------+------+------+
| status | category | 7/12 | 7/19 | ...etc for every weekEndDate entry in Targets
+--------+------------+------+------+
| 5 | actual | 1 | 1 |
| 5 | target | 4 | 5 |
| 5 | cumulative | 45 | 50 |
+--------+------------+------+------+
| 8 | actual | 2 | |
| 8 | target | 4 | 5 |
| 8 | cumulative | 45 | 50 |
+--------------+------+------+------+
I can use a crosstab query to make the date columns, but I'm not sure how to have rows for "actual", "target", and "cumulative". They aren't values in the same table, which means (I think) that a crosstab query won't be useful for this breakdown. Should I try to change GroupActual so that it puts the data in the shape I'm looking for? Kind of confused as to where to go next with this...
EDIT: I've made some headway on the crosstabs as per PowerUser's solution, but I'm having trouble with the one for Target. I modified the wizard's generated SQL in an attempt to get what I want but it's not working out. I used a version of GroupActual that only has the weekEndDate,status, and weeklyTarget columns; here's the SQL:
TRANSFORM weeklyTarget
SELECT status
FROM TargetStatus_forCrosstab_Target
GROUP BY status,weeklyTarget
PIVOT Format([weekEndDate],"Short Date");
You're almost there. The problem is that you can't do this all in a single crosstab. You need to make 3 crosstabs (one for 'actual', one for 'target', and one for 'cumulative'), then make a Union query to combine them all.
Additional Tip: In your individual crosstabs, add a Sort column. Your 'actual' crosstab will have a Sort value of 1, 'Target' will have a Sort value of 2, and 'Cumulative' will have 3. That way, when you union them together, you can get them all in the right order.