【问题标题】:SQL: How to query the distinct values for all columnsSQL:如何查询所有列的不同值
【发布时间】:2014-01-24 04:57:47
【问题描述】:

例如, 该表有 3 行 3 列:

姓名年龄性别
彼得 25 米
约翰 29 米
亚历克斯 25 米

我想查询表并得到

姓名年龄性别
彼得 25 米
约翰福音 29
亚历克斯

我试过的方法:

SELECT DISTINCT Name,Age,Gender FROM table

输出还是

姓名年龄性别
彼得 25 米
约翰 29 米
亚历克斯 25 米

如何实现每个字段都没有多余条目的表?谢谢。

感谢大家的帮助,尤其是 donPablo 的帮助。 这是我的 VBA 代码来实现这一点。由于我对 VBA 完全陌生,因此代码可能不是很干净和高效。但至少它有效。

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

【问题讨论】:

  • 结果需要这样格式化吗?
  • 不,结果只需要一个表格
  • 您是否尝试过使用 SELECT DISTINCT ColumnName FROM Table?
  • 你的意思是 SELECT DISTINCT (Name,Age,Gender) FROM Table
  • 是的。如果您可以提供您尝试过的东西,那么这个网站将最适合您,这样我们就可以看到您的要求。以 HowTo 形式提出的问题通常不会得到很好的回应(如果有的话)。

标签: sql ms-access


【解决方案1】:

通过命名三列,您可以检索该组值的不同组合。

如果您想要不同值的列表,请在选择中单独命名每个值。

SELECT DISTINCT Name FROM table

SELECT DISTINCT Age FROM table

SELECT DISTINCT Gender FROM table

如果您试图让它们像您在示例中那样显示,则必须通过一些 GUI 功能来完成。 SQL 数据库引擎不擅长显示诡计,只是处理数据。

【讨论】:

    【解决方案2】:

    我已经稍微扩展了表值,只是想看看会发生什么 --

    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
    

    然后我为 FN 开发了一个查询,后来推广到所有三个字段 --

    线索是对每个 FN/AGE/SEX 进行排序,然后加入该序列#--

    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;
    

    这给出了想要的结果--

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

    我更改了示例表中的 Sex,并添加到以下内容作为 un-Distinct 整个表的第一个排序并将 ON... 更改为 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
    

    现在得到这些结果

    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
    

    【讨论】:

    • 谢谢。这是非常有帮助的。但是,该方法存在一个限制条件。由于 LEFT JOIN 的特性,每列中不同值的数量必须随着列数的增加而减少。有什么方法可以摆脱束缚吗?我正在开发 Access 2013。
    • 我尝试使用UNION来摆脱约束,但是要找到应该添加哪个部分,应该删除哪个部分来达到与FULL OUTER JOIN相同的效果变得非常复杂跨度>
    • 只是一个想法——在 FN 排序之前,添加代码以对整个 un-Distinct 表进行排序,然后将所有内容左连接。
    【解决方案3】:

    这可能有一个 SQL 解决方案。我一直对可以做的事情感到惊讶。但是,我的回答是,这是一个完美的 VBA 应用程序。

    【讨论】:

    • 您能否详细说明一个可能的 SQL 解决方案,或者如何在 VBA 中专门实现这一点?您可能会因为在这个答案中没有足够的解释而被否决。
    • 我将使用 VBA 来解决它。我只是想弄清楚是否有一个简单的解决方案。还是谢谢。
    • 抱歉,我不会在 VBA 方面提供更多帮助,但我认为在启动 VBA 之前需要更多信息。
    猜你喜欢
    • 2023-01-11
    • 2019-02-18
    • 2023-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-26
    相关资源
    最近更新 更多