MS Access 2007: Select Unique Records - ms-access-2007

I have a table with 3 columns. I need to return all records where the records are unique in the third column. I realize this has been well documented all over, but I'm struggling.
Table: cars
Make Model Color
---- ----- -----
Ford Escort Red
Ford Taurus Black
Chevy Vista Green
The query needs to return:
Make Model Color
---- ----- -----
Ford Escort Red
Chevy Vista Green
The, i.e. one of the Ford records.
This is what I've written but it does not work...
SELECT [cars].*
FROM [cars]
LEFT JOIN (SELECT DISTINCT [cars].[Make] FROM [cars) b
ON [cars].[Make] = b.[Make];
Any help is appreciated, thanks.

SELECT a.*
FROM [cars] a
INNER JOIN (SELECT [cars].[Color] FROM [cars] GROUP BY [cars].[Color] HAVING COUNT(*)=1) b
ON a.[Color] = b.[Color];

Related

Access/SQL - Delete all instances of duplicate records with an if clause

I'm working on an access query and kinda hit a dead end. I want to delete all duplicate rows in a table that have the same value in the columns Brand, SerialNr, Seats and LastRepair that have the value "2013" in the year column.
I'm trying to delete all rows that have duplicates in those columns and the year 2013 so there isnt a single one left. (Not just delete the duplicated so there is only one left but delete all instances so there is none left)
The original table looks like this:
Brand
SerialNr
Seats
Color
LastRepair
Year
Ford
145
4
Blue
01.01.2020
2010
Ford
145
4
Red
01.01.2020
2010
Ford
145
4
Red
01.01.2020
2013
Ford
145
4
Green
01.01.2020
2013
Porsche
146
2
White
01.01.2022
2013
Ferrari
146
2
White
01.01.2022
2013
Volkswagen
147
4
Blue
01.01.2021
2017
Volkswagen
147
4
Red
01.01.2021
2013
Volkswagen
147
4
Orange
01.01.2021
2013
And the outcome table should look like this:
Brand
SerialNr
Seats
Color
LastRepair
Year
Ford
145
4
Blue
01.01.2020
2010
Ford
145
4
Red
01.01.2020
2010
Porsche
146
2
White
01.01.2022
2013
Ferrari
146
2
White
01.01.2022
2013
Volkswagen
147
4
Blue
01.01.2021
2017
I tried doing it with this question but I need the rows deleted if they have a duplicated value in the those columns so there isnt a single one left who has the same year.
I also tried to do a "find duplicates" query and make an outter join but was unsuccesful so far achieving the desired outcome. I'm thankful for any help.
DELETE Exists (SELECT 1
FROM carTable As t2
WHERE t1.Brand = t2.Brand AND t1.SerialNr = t2.SerialNr AND t1.Seats = t2.Seats AND t1.LastRepair = t2.LastRepair
HAVING Count(*) > 1
), t1.[FilNr], *
FROM carTable AS t1, carTable
WHERE (((Exists (SELECT 1
FROM carTable As t2
WHERE t1.Brand = t2.Brand AND t1.SerialNr = t2.SerialNr AND t1.Seats = t2.Seats AND t1.LastRepair = t2.LastRepair
HAVING Count(*) > 1
))<>False) AND ((t1.[year])=2013));
You can use an EXISTS subquery to identify duplicated rows and delete them.
In the subquery, we just select based on the columns you want to identify duplicates by, then check if the count is greater than 1 (since Count is an aggregate, it's in the HAVING clause).
DELETE * FROM t AS t1
WHERE EXISTS(
SELECT 1
FROM t As t2
WHERE t1.Brand = t2.Brand AND t1.SerialNr = t2.SerialNr AND t1.Seats = t2.Seats AND t1.LastRepair = t2.LastRepair
HAVING Count(*) > 1
)
AND Year = 2013
If your goal is to never have duplicate information in the "Brand" column, that can be accomplished in the table design itself. It's much more efficient to setup the table such that it limits what the user can input in certain circumstances. There's a couple ways you can do this. You can set the primary key to the Brand column, or change the "Indexed" property of that column to "Yes (No Duplicates)" If you are using an auto-number as the ID field and plan on relating a table by that ID, then the index is your best bet.

DB2 SQL Find the Id of Suppliers, who supply specific color

Find the id of the suppliers, who supply color red or blue. And is this possible to do it without using the join statement.
num suppliers color
------ ------- --------
1 Sam yellow
2 Ana black
3 Eva red
4 Tom blue
5 Simon blue
6 Ema green
id num
---- ------
01 1
02 2
03 3
04 4
05 5
05 4
And the result should be something like this:
id suppliers color
----- ------ -------
03 Eva red
04 Tom blue
05 Simon blue
05 Tom blue
My solution is this, but is still not giving me the result it should be.
Can someone, please help me?
select id, suppliers, color
from suppliers, parts
where color = 'blue' or color = 'red';
You're doing a join already - an implicit, comma separated one.
Tip of today: Always use modern, explicit JOIN syntax. Easier to write (without errors), easier to read and maintain, and easier to convert to outer join if needed!
select p.id, s.suppliers, s.color
from suppliers s
JOIN parts p ON s.num = p.num
where s.color IN ('blue', 'red')
Also use table aliases (s, p), and qualify the columns, e.g. s.num.
JOIN-free version:
select *
from
(
select p.id,
(select s.suppliers from suppliers s where s.num = p.num) suppliers,
(select s.color from suppliers s where s.num = p.num) color
from parts p
) dt
where color in ('blue', 'red');

Create view by joining three tables in SQL

I have three tables STUDENTS, SUBJECTS, RANK ,with data as -
1) STUDENTS [NAME(Primary)]
NAME
--------
Alex
Greg
2) SUBJECTS [ID(Primary)]:
ID
--------
100
101
102
3) RANK [SEQ(Primary), NAME, ID, RANK]
SEQ NAME ID RANK
------ ------- ------ ------
1 Alex 100 A
2 Greg 100 A
3 Greg 101 B
I want to create a view that should display data as
NAME ID RANK
------- ------ ------
Alex 100 A
Alex 101 Z
Alex 102 Z
Greg 100 A
Greg 101 B
Greg 102 Z
So, for every student and for every subject, the View should display the RANK if present in RANK table, else replace the NULL with 'Z'.
I'm a newbie to SQL. So any help in forming the query would be deeply appreciated!
cross join student and subject then left outer join the result with rank to get ranks for all (student, subject) combination. selecting column with NVL OR COALESCE will replace NULL with 'z'.
SELECT st.name,
su.id,
NVL(ra.rank,'Z') Rank, --COALESCE(ra.rank,'Z') Rank
FROM student st
CROSS JOIN subject su
LEFT OUTER JOIN rank ra
ON ra.name = st.name
AND ra.id = su.id
ORDER BY st.name,su.id
Note : ORDER BY can be removed from above query if you don't need.
fiddle
SELECT r.NAME, r.ID, NVL(r.RANK, 'Z')
FROM RANK r, studendts st, SUBJECTS su
WHERE st. NAME = r. NAME
AND su.ID = r.ID
ORDER BY 1,2,3

SELECT DISTINCT HAVING Count unique conditions

I've searched for an answer on this but can't find quite how to get this distinct recordset based on a condition. I have a table with the following sample data:
Type Color Location Supplier
---- ----- -------- --------
Apple Green New York ABC
Apple Green New York XYZ
Apple Green Los Angeles ABC
Apple Red Chicago ABC
Apple Red Chicago XYZ
Apple Red Chicago DEF
Banana Yellow Miami ABC
Banana Yellow Miami DEF
Banana Yellow Miami XYZ
Banana Yellow Atlanta ABC
I'd like to create a query that shows the count of unique locations for each distinct Type+Color where the number of unique locations is more than 1, e.g.
Type Color UniqueLocations
---- ----- --------
Apple Green 2
Banana Yellow 2
Note that {Apple, Red, 1} doesn't appear because there is only 1 location for red apples (Chicago). I think I've got this one (but perhaps there is a simpler method). I'm using:
SELECT Type, Color, Count(Location) FROM
(SELECT DISTINCT Type, Color, Location FROM MyTable)
GROUP BY Type, Color HAVING Count(Location)>1;
How can I create another query that lists the Type, Color, and Location for each distinct Type,Color when the count of unique locations for that Type,Color is greater than 1? The resulting recordset would look like:
Type Color Location
---- ----- --------
Apple Green New York
Apple Green Los Angeles
Banana Yellow Miami
Banana Yellow Atlanta
Note that Apple, Red, Chicago doesn't appear because there is only 1 location for red apples. Thanks!
Use a COUNT(DISTINCT Location) and join against a subquery on Type and Color The GROUP BY and HAVING clauses as you have attempted to use them will do the job.
/* Be sure to use DISTINCT in the outer query to de-dup */
SELECT DISTINCT
MyTable.Type,
MyTable.Color,
Location
FROM
MyTable
INNER JOIN (
/* Joined subquery returns type,color pairs having COUNT(DISTINCT Location) > 1 */
SELECT
Type,
Color,
/* Don't actually need to select this value - it could just be in the HAVING */
COUNT(DISTINCT Location) AS UniqueLocations
FROM
MyTable
GROUP BY Type, Color
/* Note: Some RDBMS won't allow the alias here and you
would have to use the expanded form
HAVING COUNT(DISTINCT Location) > 1
*/
HAVING UniqueLocations > 1
/* JOIN back against the main table on Type, Color */
) subq ON MyTable.Type = subq.Type AND MyTable.Color = subq.Color
Here is a demonstration
You could write your first query as this:
Select Type, Color, Count(Distinct Location) As UniqueLocations
From Table
Group By Type, Color
Having Count(Distinct Location) > 1
(if you're using MySQL you could use the alias UniqueLocations in your having clause, but on many other systems the aliases are not yet available as the having clause is evaluated before the select clause, in this case you have to repeat the count on both clauses).
And for the second one, there are many different ways to write that, this could be one:
Select Distinct Type, Color, Location
From Table
Where
Exists (
Select
*
From
Table Table_1
Where
Table_1.Type = Table.Type
and Table_1.Color = Table.Color
Group By
Type, Color
Having
Count(Distinct Location) > 1
)

Parallel SQL queries with aligned data, in MS Access

I have three tables, fruit, person and vegetable
Person
personID personName
-------- ----------
1 Ken
Fruit
personID fruitname
-------- -----
1 apple
1 orange
Vegetable
personID vegetableName
-------- -------------
1 carrot
1 tomato
1 potato
And I want the output to be like this...
personName fruitName vegetableName
---------- --------- -------------
1 apple carrot
1 orange tomato
1 potato
It lessen the duplication of outputs.. is this even possible? can when I tried it before
the values keep repeating? Is their a way to avoid it?
This is only possible if you also add a "position" column to the fruit and vegetables tables, and use this as an additional join column.
Records are not sorted in SQL. So, if you want the sorted, you ALWAYS need a sort criteria, because the SQL standard does not enforce any kind of sort order else.
If an alphabetical sort order is enought, you could dynamically add a position column by something like this (will not work in MS ACCESS, but something similar will do):
SELECT f1.personid, f1.fruitname, count(*) as position
FROM fruit f1 outer join fruit f2 on f1.fruitname = f2.fruitname
and f1.personid = f2.personid
WHERE f2.fruitname < f1.fruitname
GROUP BY f1.personid, f1.fruitname
This query has a position, starting from 0, with the names "before".
Now you can do something like:
select f.personid, f.fruitname, v.vegetablename
from (*fruitquery*) f outer join (*vegetaryquery*) v on f.personid = v.personid
and f.positionid = v.positionid;