简体   繁体   中英

SQL: How to query the distinct values for all columns

For example, The table has 3 rows and 3 columns:


Peter 25 M
John 29 M
Alex 25 M

And I want to query the table and get


Peter 25 M
John 29
Alex

The method I have tried:

SELECT DISTINCT Name,Age,Gender FROM table

The output is still


Peter 25 M
John 29 M
Alex 25 M

How to achieve the table that there is no redundant entries for every field? Thanks.

Thanks for the help from all of you, especially the help from donPablo. Here's my VBA code to achieve that. Since I am totally new to VBA, the code might not be very clean and efficient. But at least it works.

Option Compare Database

Sub ReadDistinctValue()

Dim d As Database
Dim rs As Recordset
Dim FN As Field, Age As Field, Sex As Field

Set d = CurrentDb()
Set rs = d.OpenRecordset("Table1")
Set FN = rs.Fields("FN")
Set Age = rs.Fields("Age")
Set Sex = rs.Fields("Sex")

d.Execute "CREATE TABLE Table4 (FN Text,Age Text,Sex Text)"

While Not rs.EOF
    If CheckFN(FN) = False Then
        Call WriteFN(FN)
    End If
    If CheckAge(Age) = False Then
        Call WriteAge(Age)
    End If
    If CheckSex(Sex) = False Then
        Call WriteSex(Sex)
    End If
    rs.MoveNext
Wend

rs.Close

End Sub

Function CheckFN(FN As Field) As Boolean

Dim d As Database
Dim rs_new As Recordset
Dim FN_new As Field

Set d = CurrentDb()
Set rs_new = d.OpenRecordset("Table4")
Set FN_new = rs_new.Fields("FN")

CheckFN = False

Do While Not rs_new.EOF
    If FN_new = FN Then
        CheckFN = True
        Exit Do
    End If
    rs_new.MoveNext
Loop

rs_new.Close

End Function

Function WriteFN(FN As Field)
Dim d As Database
Dim rs_new As Recordset
Dim FN_new As Field

Set d = CurrentDb()
Set rs_new = d.OpenRecordset("Table4")
Set FN_new = rs_new.Fields("FN")

If Not rs_new.EOF Then
    rs_new.MoveFirst
End If

Do While True
    If rs_new.EOF Then
        rs_new.AddNew
        FN_new = FN
        rs_new.Update
        Exit Do
    End If
    If IsNull(FN_new.Value) Then
        rs_new.Edit
        FN_new = FN
        rs_new.Update
        Exit Do
    End If
    rs_new.MoveNext
Loop
rs_new.Close
End Function

Function CheckAge(Age As Field) As Boolean

Dim d As Database
Dim rs_new As Recordset
Dim Age_new As Field

Set d = CurrentDb()
Set rs_new = d.OpenRecordset("Table4")
Set Age_new = rs_new.Fields("Age")

CheckAge = False

Do While Not rs_new.EOF
    If Age_new = Age Then
        CheckAge = True
        Exit Do
    End If
    rs_new.MoveNext
Loop

rs_new.Close

End Function

Function WriteAge(Age As Field)
Dim d As Database
Dim rs_new As Recordset
Dim Age_new As Field

Set d = CurrentDb()
Set rs_new = d.OpenRecordset("Table4")
Set Age_new = rs_new.Fields("Age")

If Not rs_new.EOF Then
    rs_new.MoveFirst
End If

Do While True
    If rs_new.EOF Then
        rs_new.AddNew
        Age_new = Age
        rs_new.Update
        Exit Do
    End If
    If IsNull(Age_new.Value) Then
        rs_new.Edit
        Age_new = Age
        rs_new.Update
        Exit Do
    End If
    rs_new.MoveNext
Loop
rs_new.Close
End Function

Function CheckSex(Sex As Field) As Boolean

Dim d As Database
Dim rs_new As Recordset
Dim Sex_new As Field

Set d = CurrentDb()
Set rs_new = d.OpenRecordset("Table4")
Set Sex_new = rs_new.Fields("Sex")

CheckSex = False

Do While Not rs_new.EOF
    If Sex_new = Sex Then
        CheckSex = True
        Exit Do
    End If
    rs_new.MoveNext
Loop

rs_new.Close

End Function

Function WriteSex(Sex As Field)
Dim d As Database
Dim rs_new As Recordset
Dim Sex_new As Field

Set d = CurrentDb()
Set rs_new = d.OpenRecordset("Table4")
Set Sex_new = rs_new.Fields("Sex")

If Not rs_new.EOF Then
    rs_new.MoveFirst
End If

Do While True
    If rs_new.EOF Then
        rs_new.AddNew
        Sex_new = Sex
        rs_new.Update
        Exit Do
    End If
    If IsNull(Sex_new.Value) Then
        rs_new.Edit
        Sex_new = Sex
        rs_new.Update
        Exit Do
    End If
    rs_new.MoveNext
Loop
rs_new.Close
End Function

By naming the three columns, you are retrieving distinct combinations of that set of values.

If you want lists of distinct values, name each individually in a select.

SELECT DISTINCT Name FROM table

SELECT DISTINCT Age FROM table

SELECT DISTINCT Gender FROM table

If you are trying to get them to display as you have in your example, that will have to be accomplished by some GUI functionality. SQL database engines are not good at display trickery, just handling data.

I have expanded the table values a little, just to see what would happen --

FN      Age Sex
Alice   28  F
Ben     19  M
Charles 33  M
Doug    23  M
Elaine  21  F
Frank   25  M
Gwen    28  F
Helen   33  F
Alice   17  F
Ben     21  F

Then I developed a single query for FN, and later generalized to all three fields --

The clue is to sequence # each FN/AGE/SEX and then join on that seq#--

SELECT 
   AB.fn,
   CD.age,
   EF.sex

FROM   
((SELECT A.fn, Count(B.fn) AS CNTfn
    FROM   
    (SELECT DISTINCT fn FROM   table1) AS A,
    (SELECT DISTINCT fn FROM   table1) AS B
    WHERE  B.fn <= A.fn
    GROUP  BY A.fn) AS AB

LEFT JOIN 
 (SELECT C.age, Count(D.age) AS CNTage
    FROM   
    (SELECT DISTINCT age FROM   table1) AS C,
    (SELECT DISTINCT age FROM   table1) AS D
    WHERE  D.age <= C.age
    GROUP  BY C.age) AS CD
ON AB.cntfn = CD.cntage)

LEFT JOIN 
 (SELECT E.sex, Count(F.sex) AS CNTsex
    FROM   
    (SELECT DISTINCT sex FROM   table1) AS E,
    (SELECT DISTINCT sex FROM   table1) AS F
    WHERE  F.sex <= E.sex
    GROUP  BY E.sex) AS EF
ON AB.cntfn = EF.CNTsex;

This gives the results desired --

FN  AGE SEX
Alice   17  F
Ben     19  M
Charles 21  
Doug    23  
Elaine  25  
Frank   28  
Gwen    33  
Helen       

I changed the Sex in my sample table, and added to the following as the first sequencing of the un-Distinct whole table and changed the ON... to XZ.cntall ...

(SELECT X.FN & X.AGE & X.SEX, Count(*) AS CNTall
FROM   
(SELECT DISTINCT FN, AGE,  SEX FROM   table1) AS X,
(SELECT DISTINCT FN, AGE,  SEX FROM   table1) AS Z
WHERE  Z.FN & Z.AGE & Z.SEX <= X.FN & X.AGE & X.SEX
GROUP  BY X.FN,  X.AGE,  X.SEX) as XZ

and now get these results

fn     age  sex
Alice   17  M
Ben     19  N
Charles 21  O
Doug    23  P
Elaine  25  Q
Frank   28  R
Gwen    33  W
Helen       X
            Y
            Z

There is probably an SQL solution for this. I am constantly amazed at what can be done. However, my answer is that this is a perfect application for VBA.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM