Order by week, data between 2 years postgresql - sql

I have a database table transaction with the following columns:
date | mccg | us_amount | country |
Sample contents are:
08/10/2016 22:00:56 | 003 | 10 | UK
14/12/2016 19:26:34 | 004 | 30 | GER
18/02/2017 05:06:22 | 018 | 100 | UK
10/03/2016 14:52:45 | 018 | 25 | UK
12/03/2016 18:02:22 | 018 | 02 | UK
I want to get a result as follows:
year_month_week | us_amount| country | mccg
2016-03-2 | 27 | UK | 018
2017-02-2 | 100 | UK | 01
I searched online for similar solutions but couldnt get any helpful ones.
I tried this query:
SELECT year_month_week as (?),us_amount,country,mccg
FROM transaction
WHERE country like 'UK' and mccg like '018'
GROUP BY year_month_week
ORDER BY year_month_week
But my problem is how to set year_month_week working, or whatever weekly format.

You can use to_char():
SELECT to_char(date, 'YYYY-MM-WW') as year_month_week,
SUM(us_amount) as us_amount, country, mccg
FROM transaction
WHERE country like 'UK' and mccg like '018'
GROUP BY year_month_week, country, mccg
ORDER BY year_month_week;
If you want other countries or mccgs, then remove the WHERE filtering.

Related

How do I output a list of columns from a row value?

I want to query and output a count of countries where residents of each country last travelled to. I have the following query:
SELECT
COUNTRY, SUM(COUNTRY_OF_LAST_TRAVEL = 'USA') AS USA
FROM BASE_TABLE
GROUP BY
COUNTRY
and the output is something like this:
Country | USA
--------- ------
Argentina | 0
Australia | 293
Bahrain | 1
....
115 more rows
Let's say I have a table with 3 columns - ID, Country_of_residence, and Country_of_last_travel - It's mostly country data where each ID# corresponds to that member's country of residence, and where they last travel to. How do I output all other country as column so I can output the count? I've tried looking into loops but I'm not getting anywhere with it. Thank you!
Expected result:
Country | USA | Japan | Country n |
--------- ------ --------
Argentina | 0 | 25 | 0 |
Australia | 293 | 0 | 12 |
Bahrain | 1 | 10 | 351 |
....
115 more rows
I'm using DBBrowser for SQLite.

result of selecting field names from table with group by

Say you're given the following table called Customers:
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Hardik | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Ramesh | 25 | Ahmedabad | 6500.00 |
| 5 | Hardik | 27 | Delhi | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
| 7 | Ramesh | 24 | Ahmedabad | 10000.00 |
+----+----------+-----+-----------+----------+
A lot of resources explaining group by statements would use an example like:
SELECT NAME, SUM(SALARY) FROM CUSTOMERS GROUP BY NAME; where the thing being 'selected' other than the field being 'grouped by' is a function like count or sum. But what happens if you did something like SELECT NAME, ADDRESS FROM CUSTOMERS GROUP BY NAME; - how exactly would the addresses be grouped together in a single record with the name. I know I can run this and find out the answer, but I want to understand the general logic - if anyone could assist that would be very much appreciated.
EDIT ANOTHER QUESTION:
In the new table above, if I did SELECT NAME, ADDRESS, group_concat(salary) FROM CUSTOMERS GROUP BY NAME; would this be ok, seeing as how the addresses are the same for each name?
If you say SELECT NAME, ADDRESS FROM CUSTOMERS GROUP BY NAME, you will get an error asking you to put an aggregation function around the ADDRESS column. For instance, you could write
SELECT NAME, MAX(ADDRESS) FROM CUSTOMERS GROUP BY NAME

Count how many times certain fields in records with repeating values are found (or not found) in another table

First of all, I wish to say hi to the community here. The posts here have been a great help with VBA but this is my first question ever. I have a task that I need to solve in SQL (in MS Access) but it's sort of new to me and the task seems to be too complex.
I have a table in Access with the following structure(let's call it Tinvoices):
invoice | year | date | company | step | agent
5110001 | 2019 | 15/01/2019 | 1201 | 0 | John
5110001 | 2019 | 15/01/2019 | 1201 | 1 | Jack
5110002 | 2019 | 10/02/2019 | 1202 | 0 | John
5110002 | 2019 | 10/02/2019 | 1202 | 1 | Jack
5110002 | 2019 | 10/02/2019 | 1202 | 2 | Daniel
5110002 | 2019 | 10/02/2019 | 1202 | 3 | John
5110003 | 2019 | 12/03/2019 | 1205 | 0 | Jack
5110003 | 2019 | 12/03/2019 | 1205 | 1 | Daniel
5110003 | 2019 | 12/03/2019 | 1205 | 2 | David
This table relates to actions on invoices. Invoices and their related data are repeated with each step.
There is another table, which contains agents belonging to a certain department (let's call it Tdeptusers):
agent
John
Jack
What I need to do is the following. Have distinct lines for the invoices (the most unique key is combining the invoice, year and company) and counting in separate steps have been done by users in the Tdeptusers table and how many by users who are not in Tdeptusers. Something like this:
invoice | year | month | company | actionsByOurDept | actionsByOthers
5110001 | 2019 | 1 | 1201 | 2 | 0
5110002 | 2019 | 2 | 1202 | 3 | 1
5110003 | 2019 | 3 | 1205 | 1 | 2
I'm kind of a beginner, so you'll have to excuse me in providing usable codes. Being a complete beginner, I got stuck after the absolute basics. I have stuff like this:
SELECT
invoice,
year,
DatePart("m", Date) AS month,
company,
Sum(IIf(i.agent IN(d.agent), 1, 0)) AS actionsByOurDept,
Sum(IIf(i.agent IN(d.agent), 0, 1)) AS actionsByOthers
FROM Tinvoices AS i, Tdeptusers AS d
GROUP BY invoice, year, DatePart("m", Date), company;
This doesn't give back the desired result, mostly not in actionsByOthers, instead I get huge numbers. Maybe something similar to this solution might work but I haven't been able to do it.
Much appreciation for the help, folks.
Use proper standard explicit JOIN syntax :
SELECT i.invoice, year, DatePart("m", i.Date) AS month, i.company,
SUM( IIF(d.agent IS NOT NULL, 1, 0) ) AS actionsByOurDept,
SUM( IIf(d.agent IS NULL, 1, 0) ) AS actionsByOthers
FROM Tinvoices AS i LEFT JOIN
Tdeptusers AS d
ON d.agent = i.agent
GROUP BY i.invoice, i.year, DatePart("m", i.Date), i.company;
Use left join:
SELECT invoice, year, DatePart("m", Date) AS month, company,
COUNT(d.agent) AS actionsByOurDept,
SUM(IIF(d.agent IS NULL, 1, 0)) AS actionsByOthers
FROM Tinvoices AS i LEFT JOIN
Tdeptusers AS d
ON d.agent = i.agent
GROUP BY invoice, year, DatePart("m", Date), company;
You can directly count your department's users using COUNT().

Comparing SUM of values with different tables in SQL Server

I have two tables holding similar values, and I need to compare the two and find the differences between them:
SQL FIDDLE - http://sqlfiddle.com/#!6/7412e/9
Now you can see there is a difference between between the 2 tables for the figures in Jun-17.
AS you can see (as a total for everyone) table 1 has £75 for June but table 2 has £125 for june.
The result I'm looking for is when amounts are summed together and compared between tables on a monthly basis, if there is a difference in amount between the two tables I want it listed under 'Unknown'.
| MonthYear | Person | Amount | Month total
+-----------+--------+--------+--------------
| Jun-17 | Sam | 25 | 75(Table1)
| Sep-17 | Ben | 50 | 50(Table2)
| Jun-17 | Tom | 50 | 75(Table1)
| Jun-17 | Sam | 25 | 125(Table2)
| Sep-17 | Ben | 50 | 50(Table2)
| Jun-17 | Tom | 50 | 125(Table2)
| Jun-17 | | 50 | 125(Table2)
Now when there is a difference between the amount total over a month I want the difference to be classed as unknown
e.g
| MonthYear | Person | Amount | Month total
+-----------+--------+--------+--------------
| Jun-17 | Sam | 25 | 75(Table1)
| Sep-17 | Ben | 50 | 50(Table2)
| Jun-17 | Tom | 50 | 75(Table1)
| Jun-17 | Sam | 25 | 125(Table2)
| Sep-17 | Ben | 50 | 50(Table2)
| Jun-17 | Tom | 50 | 125(Table2)
| Jun-17 | Unknown| 50 | 125(Table2)
I understand that you could create a case when the person is null to display unknown but i need it to be specifically calculated on the difference between the 2 tables on a monthly calculation.
Does this make sense to anyone, its really hard to explain.
Generally, in any FROM clause a table name can be replaced with another SELECT as long as you give it a corelation name (t1 and t2 in this one):
SELECT t1.MonthYear, t1.AmountT1, t2.AmountT2, t1.amountT1 - isnull(t2.amountT2, 0) as Unknown'
from
( SELECT
MonthYear,
SUM(Amount) AS [AmountT1]
FROM
Invoice
GROUP BY MonthYear) t1
left outer join
( SELECT
MonthYear,
SUM(Amount) AS [AmountT2]
FROM
Invoice2
GROUP BY MonthYear) t2 on t2.MonthYear = t1.MonthYear

How to delete some similar rows from a table?

I have two tables, Countries and Sums:
+------+---------+
| code | country |
+------+---------+
| 01 | France |
| 02 | Germany |
| 02 | Austria |
| 03 | Belgium |
| 04 | Belgium |
| 04 | Spain |
| 05 | Italy |
+------+---------+
+------+-----+
| code | sum |
+------+-----+
| 01 | 500 |
| 02 | 400 |
| 03 | 300 |
| 04 | 200 |
+------+-----+
I want to create a table code-sum-country. It's very easy of course, but I need to have exactly the same number of rows as in the table Sums.
+------+-----+---------+
| code | sum | country |
+------+-----+---------+
| 01 | 500 | France |
| 02 | 400 | Austria |
| 02 | 400 | Germany |
| 03 | 300 | Belgium |
| 04 | 200 | Spain |
| 04 | 200 | Belgium |
+------+-----+---------+
I want to have in the above table unique code values. So I need to remove some of them, it doesn't matter which one. My goal is to have only one row with the same code. For example the row
| 04 | 200 | Spain |
can remain or be deleted.
How can I do that?
Try this:
DELETE
FROM code_sum_country
WHERE code in
(SELECT code
FROM code_sum_country
GROUP BY code
HAVING COUNT (code) > 1)
AND country NOT IN
(SELECT MIN(country)
FROM code_sum_country
GROUP BY code
HAVING COUNT (code) > 1)
This will retain the country whose name is minimum in alphabetical order.
Change MIN(country) to MAX(country) if you want to retain the maximal ones.
Hope it helps :)
If you want to query sums and get one arbitrary country, you can use a correlated subquery:
select s.*,
(select top 1 c.country
from countries as c
where s.code = c.code
) as country
from sums as s;
I understand your question in such a way that the result is actually about code and sum, and an example of country is desired. Probably to give more meaning to your results and which country is actually returned is irrelevant... I therefore suggest a group by and a max or min on code, and max or min on country. See beneath.
PS: possibly it could be more usefull to define a different kind of name that is more meaningfull than country. But that is kind of bluntly to say without more info :).
select
min(code) as code
,[sum]
,min(country) as country
from TableAA
group by sum