sql including null values in transform statement ms-access - sql

I need help including null values in my query. Let's say I have this table:
table1:
| in/out | year | name |
| in | 2011-12| jim
| in | 2011-12| tim
| in | 2012-13| toby
| out | 2011-12| ron
| out |2012-13 | jim
| out |2012-13 | joel
I created this transform statement:
Transform Count(*)
SELECT [in/out] FROM table1 WHERE name = "jim" GROUP BY [in/out]
PIVOT year IN("2011-12", "2012-13");
To get this table:
|in/out| 2011-12 | 2012-13
| in | 1 | 1
The thing is I want to include all in/out values even if they are null so for this example I'd want the table to look like this:
|in/out| 2011-12 | 2012-13
| in | 1 | 1
| out | |
Any help would be greatly appreciated. Thanks!

Related

PostgreSQL check if value exists in another table

I'm trying to find a solution in PostgreSQL of how I can add to the output of the query extra column with value if id exists in another table or not:
I need several things:
Do a join between two tables
Add a new column into the result output where I check if exists in the third table or not
My tables:
announcement
author
chapter
announcement table
| id | author_id | date | group_id | ... |
author table
| id | name | email | ... |
chapter table
| id | announcement_id | ... |
This is what I have now. I did a left outer join and it works as I expected:
select announcement.id, announcement.date, author.id as publisher_id, author.name as publisher_name
from announcement
left outer join author
on announcement.author_id = author.id
where announcement.group_id = 123 and announcement.date >= '2022-06-01'::date;
with output:
| id | date | publisher_id | publisher_name |
| 1 | 2020-07-01 | 12 | John |
| 2 | 2020-07-04 | 123 | Arthur |
Now I can't find a solution of how to add an extra column with_chapters to the query response, where I will check if announcement.id exists in chapter table under announcement_id column.
For example, chapter table can have such data:
| id | announcement_id |
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
So we see that some announcements can appear in chapters several times (so i'm looking for at least 1 match). And some announcements doesn't have chapters at all.
Output finally should be like that:
| id | date | publisher_id | publisher_name | with_chapters |
| 1 | 2020-07-01 | 12 | John | true |
| 2 | 2020-07-04 | 123 | Arthur | false |
Thanks a lot for any help :)
While EXISTS (subquery) is usually used in the WHERE clause, it returns an ordinary Boolean and so can be used in the select list.
SELECT blah1, blah2,
EXISTS (select 1 from chapter where chapter.announcement_id=announcement.id) as with_chapter
FROM ...

Add column to table with set values for every row expanding the table

I'm trying to add a column to a table in Redshift that adds multiple values to all the rows but has no relation, apart from all rows should be affected.
I'm not sure how to describe this so Google-ing is proving tough!
Visual example:
+----+-------+
| ID | Name |
+----+-------+
| 1 | James |
| 2 | Jane |
+----+-------+
Should become
+----+-------+-----+
| ID | Name | Sec |
+----+-------+-----+
| 1 | James | SG1 |
| 1 | James | SG2 |
| 1 | James | SG3 |
| 2 | Jane | SG1 |
| 2 | Jane | SG2 |
| 2 | Jane | SG3 |
+----+-------+-----+
Basically added "SG1, SG2, and SG3" to every row.
Thanks,
You can cross join a derived table that contains the three values:
select t.id, t.name, s.sec
from mytable t
cross join (select 'SG1' sec union all select 'SG2' union all select 'SG3') s
I am unsure whether Redshift supports values(), which would help shortening the syntax:
select t.id, t.name, s.sec
from mytable t
cross join (values ('SG1'), ('SG2'), ('SG3')) s(sec)

SQL: tricky question for finding lockout dates

Hope you can help. We have a table with two columns Customer_ID and Trip_Date. The customer receives 15% off on their first visit and on every visit where they haven't received the 15% off offer in the past thirty days. How do I write a single SQL query that finds all days where a customer received 15% off?
The table looks like this
+-----+-------+----------+
| Customer_ID | date |
+-----+-------+----------+
| 1 | 01-01-17 |
| 1 | 01-17-17 |
| 1 | 02-04-17 |
| 1 | 03-01-17 |
| 1 | 03-15-17 |
| 1 | 04-29-17 |
| 1 | 05-18-17 |
+-----+-------+----------+
The desired output would look like this:
+-----+-------+----------+--------+----------+
| Customer_ID | date | received_discount |
+-----+-------+----------+--------+----------+
| 1 | 01-01-17 | 1 |
| 1 | 01-17-17 | 0 |
| 1 | 02-04-17 | 1 |
| 1 | 03-01-17 | 0 |
| 1 | 03-15-17 | 1 |
| 1 | 04-29-17 | 1 |
| 1 | 05-18-17 | 0 |
+-----+-------+----------+--------+----------+
We are doing this work in Netezza. I can't think of a way using just window functions, only using recursion and looping. Is there some clever trick that I'm missing?
Thanks in advance,
GF
You didn't tell us what your backend is, nor you gave some sample data and expected output nor you gave a sensible data schema :( This is an example based on guess of schema using postgreSQL as backend (would be too messy as a comment):
(I think you have Customer_Id, Trip_Date and LocationId in trips table?)
select * from trips t1
where not exists (
select * from trips t2
where t1.Customer_id = t2.Customer_id and
t1.Trip_Date > t2.Trip_Date
and t1.Trip_date - t2.Trip_Date < 30
);

Calculate Final outcome based on Results/ID

For a Table T1
+----------+-----------+-----------------+
| PersonID | Date | Employment |
+----------+-----------+-----------------+
| 1 | 2/28/2017 | Stayed the same |
| 1 | 4/21/2017 | Stayed the same |
| 1 | 5/18/2017 | Stayed the same |
| 2 | 3/7/2017 | Improved |
| 2 | 4/1/2017 | Stayed the same |
| 2 | 6/1/2017 | Stayed the same |
| 3 | 3/28/2016 | Improved |
| 3 | 5/4/2016 | Improved |
| 3 | 4/19/2017 | Worsened |
| 4 | 5/19/2016 | Worsened |
| 4 | 2/16/2017 | Improved |
+----------+-----------+-----------------+
I'm trying to calculate a Final Result field partitioning on Employment/PersonID fields, based on the latest result/person relative to prior results. What I mean by that is explained in the logic behind Final Result:
For every Person,
If all results/person are Stayed the same, then only should final
result for that person be "Stayed the same"
If Worsened/Improved
are in the result set for a person, the final result should be the
latest Worsened/Improved result for that person, irrespective of "Stayed the same" after a W/I result.
Eg:
Person 1 Final result -> Stayed the same, as per (1)
Person 2 Final result -> Improved, as per (2)
Person 3 Final result -> Worsened, as per (2)
Person 4 Final result -> Improved, as per (2)
Desired Result:
+----------+-----------------+
| PersonID | Final Result |
+----------+-----------------+
| 1 | Stayed the same |
| 2 | Improved |
| 3 | Worsened |
| 4 | Improved |
+----------+-----------------+
I know this might involve Window functions or Sub-queries but I'm struggling to code this.
Hmmm. This is a prioritization query. That sounds like row_number() is called for:
select t1.personid, t1.employment
from (select t1.*,
row_number() over (partition by personid
order by (case when employment <> 'Stayed the same' then 1 else 2 end),
date desc
) as seqnum
from t1
) t1
where seqnum = 1;

Create a pivot table from two tables based on dates

I have two MS Access tables sharing a one to many relationship. Their structures are like the following:
tbl_Persons
+----------+------------+-----------+
| PersonID | PersonName | OtherData |
+----------+------------+-----------+
| 1 | PersonA | etc. |
| 2 | PersonB | |
| 3 | PersonC | |
tbl_Visits
+----------+------------+------------+-----------------------
| VisitID | PersonID | VisitDate | dozens of other fields
+----------+------------+------------+-----------
| 1 | 1 | 09/01/13 |
| 2 | 1 | 09/02/13 |
| 3 | 2 | 09/03/13 |
| 4 | 2 | 09/04/13 | etc...
I wish to create a new table based on the VisitDate field, the column headings of which are Visit-n where n is 1 to the number of visits, Visit-n-Data1, Visit-n-Data2, Visit-n-Data3 etc.
MergedTable
+----------+----------+---------------+-----------------+----------+----------------+
| PersonID | Visit1 | Visit1Data1 | Visit1Data2... | Visit2 | Visit2Data1... |
+----------+----------+---------------+-----------
| 1 | 09/01/13 | | | 09/02/13 |
| 2 | 09/03/13 | | | 09/04/13 |
| 3 | etc. | |
I am really not sure how to do this. Whether SQL query or using DAO then looping through records and columns. It is essential that there is only 1 PersonID per row and all his data appears chronologically into columns.
Start of by ranking the visits with something like
SELECT PersonID, VisitID,
(SELECT COUNT(VisitID) FROM tbl_Visits AS C
WHERE C.PersonID = tbl_Visits.PersonID
AND C.VisitDate < tbl_Visits.VisitDate) AS RankNumber
FROM tbl_Visits
Use this query as a base for the 'pivot'
Since you seem to have some visits of persons on the same day (visit 1 and 2) the WHERE clause needs to be a bit more sophisticated. But I hope you get the basic concept.
Pivoting can be done with multiple LEFT JOINs.
I question if my solution will have a high performance, since I did not test it. It is easier in SQL Server than in MS Access to accomplish.