MS Access pull down column via query - sql

I have the following table in MS Access:
ID | column1 | column2 | column3
---+---------+-------------------+--------------
1 | A | Publishers | Publishers
2 | 01 | Commercial |
3 | 02 | University Press |
4 | B | Place | Place
5 | 01 | United States |
6 | 04 | Western Europe |
7 | 05 | Other |
8 | C | Language | Language
9 | 01 | English |
10 | 02 | French |
I am looking for the following result
ID |column1 | column2 | column3
---+---------+-------------------+--------------
1 | A | Publishers | Publishers
2 | 01 | Commercial | Publishers
3 | 02 | University Press | Publishers
4 | B | Place | Place
5 | 01 | United States | Place
6 | 04 | Western Europe | Place
7 | 05 | Other | Place
8 | C | Language | Language
9 | 01 | English | Language
10 | 02 | French | Language
So basically pulling down column3 heading. I have tried searching the net and asking other pals with some ms access knowledge. But really couldn't find any "pull down" query. Copy/paste wouldn't suffice as this will be performed many times in a day and with much larger data set. Can this be done without vba (looking to get this done through a query)?

If you have a column that specifies the ordering, you can do this with a correlated subquery:
select column1, column2,
(select top (1) t2.column3
from t as t2
where t2.id <= t.id and
t2.column3 is not null
order by t2.id desc
) as column3
from t;

Related

Exclude subsets from a table which has superset values too

Table1 has employee ids and codes where each employee has both super-set code and subset codes.
+-------------+------+
| Employee ID | Code |
+-------------+------+
| 111 | 18 |
| 111 | 19 |
| 111 | 20 |
| 111 | 21 |
| 222 | 40 |
| 222 | 41 |
| 222 | 42 |
+-------------+------+
Table2 has super-set code and subset code.
+---------------+-------------+
| Superset code | Subset code |
+---------------+-------------+
| 18 | 19 |
| 18 | 20 |
| 18 | 21 |
| 40 | 41 |
| 40 | 42 |
+---------------+-------------+
I want output with employee id and super-set code alone.
Expected result table:
+-------------+------+
| Employee ID | Code |
+-------------+------+
| 111 | 18 |
| 222 | 40 |
+-------------+------+
How can I derive this output using sql query?
I think you want exists:
select t1.*
from table1 t1
where exists (select 1 from table2 t2 where t2.supersetcode = t1.code);
For performance, you want an index on table2(supersetcode).

Access - retrieving status and date puzzle

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.

Select rows with the same attribute1 and different attribute2

I have a table
+----+------+---------+
| ID | CODE | COUNTRY |
+----+------+---------+
| 1 | 05 | France |
| 2 | 05 | France |
| 3 | 06 | Germany |
| 4 | 07 | France |
| 5 | 07 | Italy |
+----+------+---------+
and I need to select rows with the same code but different country.
So the result should be:
+------+---------+
| CODE | COUNTRY |
+------+---------+
| 07 | France |
| 07 | Italy |
+------+---------+
I tried
SELECT t1.code AS code, t1.country AS country
FROM countries AS t1, countries AS t2
WHERE t1.code = t2.code
AND t1.country <> t2.country;
and it works for the table in the example above.
But if the table looks like this:
+----+------+---------+
| ID | CODE | COUNTRY |
+----+------+---------+
| 1 | 05 | France |
| 2 | 05 | France |
| 3 | 06 | Germany |
| 4 | 07 | France |
| 5 | 07 | Italy |
| 6 | 07 | Italy |
+----+------+---------+
the result is:
+------+---------+
| CODE | COUNTRY |
+------+---------+
| 07 | Italy |
| 07 | Italy |
| 07 | France |
| 07 | France |
+------+---------+
but should be the same as above.
(I work with MS Access, so the query should work on Access)
Just add distinct
SELECT DISTINCT t1.code AS code, t1.country AS country
FROM countries AS t1, countries AS t2
WHERE t1.code = t2.code
AND t1.country <> t2.country;
You can use MIN and MAX to spot Codes where the Country is different, then use that to select all rows:
SELECT * FROM countries WHERE Code IN (
SELECT Code
FROM countries
GROUP BY Code
HAVING MIN(Country) < MAX(Country)
)

Sub query in t sql select statement

I have a query which lists users but it requires a sub query to get whether they are available today. I need the fourth column 'Availability' to iterate through each user and display if they have availability or display a null. I've tried everything I can think of sub queries, cursors etc but no joy. Any pointers welcome!
SELECT inter.authno,
inter.FirstName,
inter.Surname,
COALESCE((
Select at.typeName as [Availability]
FROM [database].[dbo].[Interviewer] inter
full join [database].[dbo].[availability] av
on inter.authno = av.authno
full join [database].[dbo].[availability_days] ad
on av.availID = ad.availID
full join [database].[dbo].[availibiltyType] at
on av.typeID = at.typeid
where exists(
select authno
from [database].[dbo].[Interviewer]
)
and ad.actualDay = '2015-05-21'
), null ) AS [Availability]
FROM [database].[dbo].[Interviewer] inter
The query gives the below results, but it should only show Available for Harry Kane and the rest should be null.
authno FirstName Surname Availability
-------------------------------------
10 Minch Yoda Available
11 Darth Vadar Available
12 Darth Maul Available
14 Obi Wan Kenobi Available
15 Qui-Gon Jinn Available
16 Darth Sidious Available
17 Boba Fett Available
24 Harry Kane Available
39 mark o'neill Available
I also tried the code suggestion below kindly provided which gives some results I need, but it shows all of the results instead of the availability type for today.
SELECT
inter.authno,
inter.FirstName,
inter.Surname,
at.typeName as [Availability]
FROM [database].[dbo].[Interviewer] inter
left JOIN [database].[dbo].[availability] av
on inter.authno = av.authno
left JOIN [database].[dbo].[availability_days] ad
on av.availID = ad.availID
and ad.actualDay = '2015-07-21'
left JOIN [database].[dbo].[availibiltyType] at
on av.typeID = at.typeid
Output:
+----+---------+-----------+--------------+
| 10 | Minch | Yoda | NULL |
+----+---------+-----------+--------------+
| 11 | Darth | Vadar | NULL |
| 12 | Darth | Maul | NULL |
| 13 | Luke | Skywalker | NULL |
| 14 | Obi Wan | Kenobi | NULL |
| 15 | Qui-Gon | Jinn | Annual Leave |
| 16 | Darth | Sidious | NULL |
| 17 | Boba | Fett | UO |
| 17 | Boba | Fett | Available |
| 18 | test22 | test33 | NULL |
| 19 | test7 | test7 | NULL |
| 22 | Bob | Marley | NULL |
| 23 | JO | JO | NULL |
| 24 | Harry | Kane | Annual Leave |
| 24 | Harry | Kane | Available |
| 24 | Harry | Kane | Available |
| 24 | Harry | Kane | Annual Leave |
| 24 | Harry | Kane | Annual Leave |
| 24 | Harry | Kane | NW |
| 24 | Harry | Kane | NW |
| 24 | Harry | Kane | Available |
| 39 | mark | o'neill | US |
+----+---------+-----------+--------------+
I also tried the below which gets me the exact results that I need only that, I need to display all users whether they have a date in the table or not. i.e. If I change the date to last weer Harry Kane disappears.
SELECT
inter.authno,
inter.FirstName,
inter.Surname,
at.typeName as [Availability]
FROM [database].[dbo].[Interviewer] inter
left JOIN [database].[dbo].[availability] av
on inter.authno = av.authno
left JOIN [database].[dbo].[availability_days] ad
on av.availID = ad.availID
left JOIN [database].[dbo].[availibiltyType] at
on av.typeID = at.typeid
where ad.actualDay = '2015-05-21'or ad.actualDay is null
Output for today:
+--------+-----------+-----------+--------------+
| authno | FirstName | Surname | Availability |
+--------+-----------+-----------+--------------+
| 10 | Minch | Yoda | NULL |
| 11 | Darth | Vadar | NULL |
| 12 | Darth | Maul | NULL |
| 13 | Luke | Skywalker | NULL |
| 14 | Obi Wan | Kenobi | NULL |
| 16 | Darth | Sidious | NULL |
| 18 | test22 | test33 | NULL |
| 19 | test7 | test7 | NULL |
| 22 | Bob | Marley | NULL |
| 23 | JO | JO | NULL |
| 24 | Harry | Kane | Available |
+--------+-----------+-----------+--------------+
Output for 2015-05-10
+--------+-----------+-----------+--------------+
| authno | FirstName | Surname | Availability |
+--------+-----------+-----------+--------------+
| 10 | Minch | Yoda | NULL |
| 11 | Darth | Vadar | NULL |
| 12 | Darth | Maul | NULL |
| 13 | Luke | Skywalker | NULL |
| 14 | Obi Wan | Kenobi | NULL |
| 16 | Darth | Sidious | NULL |
| 18 | test22 | test33 | NULL |
| 19 | test7 | test7 | NULL |
| 22 | Bob | Marley | NULL |
| 23 | JO | JO | NULL |
+--------+-----------+-----------+--------------+
If I understand correctly, you want a correlated subquery for your version of the query:
SELECT inter.authno,
inter.FirstName,
inter.Surname,
(Select at.typeName as [Availability]
FROM [database].[dbo].[availability] av join
[database].[dbo].[availability_days] ad
on av.availID = ad.availID join
[database].[dbo].[availibiltyType] at
on av.typeID = at.typeid
where inter.authno = av.authno and ad.actualDay = '2015-05-21'
) AS [Availability]
FROM [database].[dbo].[Interviewer] inter;
Some notes:
COALESCE(<x>, NULL) doesn't make sense. Just use <X>
With a subquery, you should use IFNULL() rather than COALESCE(), because SQL Server has (what I consider to be) a flawed implementation of COALESCE().
Your subquery needs to be correlated to the outer query.
I have no idea what the EXISTS clause was supposed to do. If the table has any rows, then it would always return TRUE.
There is no reason for full joins in the subquery.
I would expect your version to return the error "subquery returns more than one row".
Without seeing your table structure It's a guess, but an educated one.
Try this:
SELECT inter.authno,
inter.FirstName,
inter.Surname,
at.typeName as [Availability]
FROM [database].[dbo].[Interviewer] inter
LEFT JOIN [database].[dbo].[availability] av on inter.authno = av.authno
LEFT JOIN [database].[dbo].[availability_days] ad on av.availID = ad.availID and ad.actualDay = '2015-05-21'
LEFT JOIN [database].[dbo].[availibiltyType] at on av.typeID = at.typeid
For future sql questions you might have, Please include the relevant tables DDL, some sample data (preferably as DML statements), and the desired output.

JOIN solution on Postgres with many tables

Little issue on a Postgres database, being managed in Acqua Data Studio:
I need a solution to create a SELECT that concatenates many views into one table. There are more than 10 views.
One central may have many IDs, and one ID may have many centrals. So, the main table's PK would be the central-ID thing.
One example that applies (assuming that exist only 3 tables), as follows:
VIEW1:
central | ID | MAP
--------------------------------
A | 01 | MAP1
A | 02 | MAP1
A | 03 | -
B | 01 | MAP3
B | 02 | -
C | 01 | -
VIEW2:
central | ID | CAMEL
--------------------------------
A | 01 | CAP1
B | 01 | CAP1
B | 02 | CAP2
B | 03 | CAP3
D | 01 | -
VIEW3:
central | ID | NRRG
--------------------------------
A | 01 | NRRG2
B | 01 | -
C | 01 | -
D | 05 | NRRG1
.
.
.
Resulting Table:
central | ID | MAP | CAMEL | NRRG
--------------------------------------------------
A | 01 | MAP1 | CAP1 | NRRG2
A | 02 | MAP1 | |
A | 03 | - | |
B | 01 | MAP3 | CAP1 | -
B | 02 | - | CAP2 |
B | 03 | | CAP3 |
C | 01 | - | | -
D | 01 | | - |
D | 05 | | | NRRG1
Any central-ID that appears in any of the 10+ tables need to enter in the concatenated table.
I surely don't care about blank spaces on those columns that don't have a correspondent into the other columns...
The important thing is to get, in each ID-central row every correspondent value that is present on the other tables. PS: "-" is a value!
I thought about a FULL OUTER JOIN, but whatching the references in manual I can't see a way to do it perfectly...
Thanks, fellas!
SQL Fiddle
select central, id, map, camel, nrrg
from
v1
full outer join
v2 using (central, id)
full outer join
v3 using (central, id)
order by central, id
;
central | id | map | camel | nrrg
---------+----+------+-------+-------
A | 1 | MAP1 | CAP1 | NRRG2
A | 2 | MAP1 | |
A | 3 | | |
B | 1 | MAP3 | CAP1 |
B | 2 | | CAP2 |
B | 3 | | CAP3 |
C | 1 | | |
D | 1 | | |
D | 5 | | | NRRG1
A full outer join is extra complicated when you have composite keys. Instead, use the union all/group by method:
select central, id, max(map) as map, max(camel) as camel, max(nrrg) as nrrg
from ((select central, id, map, null as camel, null as nrrg
from view1
) union all
(select central, id, null as map, camel, null as nrrg
from view2
) union all
(select central, id, null as map, null as camel, nrrg
from view3
)
) v
group by central, id;