ChatGPT解决这个技术问题 Extra ChatGPT

SQL/mysql - 选择不同/唯一但返回所有列?

SELECT DISTINCT field1, field2, field3, ......   FROM table

我正在尝试完成以下 sql 语句,但我希望它返回所有列这可能吗?就像是:

SELECT DISTINCT field1, * from table
为什么 SELECT DISTINCT * FROM table 不适合您?
如果您的表有 PK,则所有行都应按定义为 distinct。如果您尝试仅选择 DISTINCT field1 但以某种方式返回所有其他列,那么对于特定 field1 值具有多个值的那些列会发生什么情况?例如,您需要在其他列上使用 GROUP BY 和某种聚合。
如果您想要重复的行而不仅仅是不同的行,请删除 distinct 关键字。
你能举例说明你期望的结果是什么样的吗?到目前为止,我无法理解您想要的查询。
这是类似问题的答案,您需要先获取带有其 id 的不同列,然后将其与原始表连接。 SELECT DISTINCT on one column, return multiple other columns

C
Community

您正在寻找一个组:

select *
from table
group by field1

有时可以用不同的 on 语句编写:

select distinct on field1 *
from table

然而,在大多数平台上,上述两种方法都不起作用,因为其他列上的行为是未指定的。 (第一个在 MySQL 中有效,如果你正在使用的话。)

您可以获取不同的字段并坚持每次都选择一个任意行。

在某些平台(例如 PostgreSQL、Oracle、T-SQL)上,这可以直接使用窗口函数来完成:

select *
from (
   select *,
          row_number() over (partition by field1 order by field2) as row_number
   from table
   ) as rows
where row_number = 1

在其他(MySQL、SQLite)上,您需要编写子查询,使您可以将整个表与自身连接起来(example),因此不推荐。


该查询不会为我解析并给出错误:The ranking function "row_number" must have an ORDER BY clause。我们需要在按 field1 分区后添加 order by 子句。所以正确的查询是 select * from ( select *, row_number() over (partition by field1 order by orderbyFieldName) as row_number from table ) as rows where row_number = 1
谢谢!我遇到了同样的问题,解决方案是 GROUP BY
同样在 Oracle (Oracle SQL Developer) 中,您不能指定 select *, row_number() over (partition by field1 order by field2) as row_number from table。您必须在选择查询 select **table**.*, row_number() over (partition by field1 order by field2) as row_number from table 中显式使用表名/别名
@jarlh:可能是……今天。正如您可能注意到的那样,这个答案已经有将近 7 年的历史了,就我在活动时回想起的情况而言,情况并非如此。如果您认为有必要,欢迎您重新标记和/或编辑答案。
select distinct on (field1) * from table;也适用于 PostgreSQL
J
Jin Kwon

从您的问题的措辞中,我了解到您希望为给定字段选择不同的值,并为每个这样的值选择同一行中的所有其他列值。大多数 DBMS 不允许使用 DISTINCTGROUP BY,因为结果未确定。

可以这样想:如果您的 field1 出现不止一次,将列出 field2 的什么值(假设您在两行中有相同的 field1 值,但其中有两个不同的 field2 值两行)。

但是,您可以使用聚合函数(明确针对您想要显示的每个字段)并使用 GROUP BY 而不是 DISTINCT

SELECT field1, MAX(field2), COUNT(field3), SUM(field4), ....
FROM table GROUP BY field1

对此解决方案 +1。所以我们可以做SELECT field1, MIN(field2), MIN(field3), MIN(field4), .... FROM table GROUP BY field1,field2,3,4,,,不需要是整数(或其他数字),也可以是char字段
工作得很好,直到我卡在一个布尔列上。 MIN(Dynamic) 列值被修改为 false,即使它是 true。任何其他可用于处理布尔值的聚合函数 - signonsridhar 6 分钟前。 Sum(dynamic) 将 false 更改为 1
很好的建议,让我找到了我认为更通用的解决方案——看看吧!
@signonsridhar 将您的布尔值转换为 int 并使用 sum;例如sum(cast(COL as int)) > 0
r
rocklandcitizen

如果我正确理解了您的问题,它与我刚刚遇到的问题相似。您希望能够将 DISTINCT 的可用性限制在指定的字段中,而不是将其应用于所有数据。

如果您在没有聚合函数的情况下使用 GROUP BY,那么您 GROUP BY 的哪个字段将是您的 DISTINCT 字段。

如果您进行查询:

SELECT * from table GROUP BY field1;

它将基于 field1 的单个实例显示您的所有结果。

例如,如果您有一个包含名称、地址和城市的表。一个人记录了多个地址,但是你只想要一个人的地址,可以查询如下:

SELECT * FROM persons GROUP BY name;

结果将是该名称的一个实例及其地址将出现,而另一个实例将从结果表中省略。注意:如果您的文件具有原子值,例如 firstName、lastName,您希望按两者进行分组。

SELECT * FROM persons GROUP BY lastName, firstName;

因为如果两个人的姓氏相同,而您仅按姓氏分组,则结果中将省略其中一个人。你需要考虑这些事情。希望这可以帮助。


如已接受的答案中所述,适用于大多数 SQL 化身——仅适用于 MYSQL
U
Ulf Sanne

这是一个非常好的问题。我已经在这里阅读了一些有用的答案,但也许我可以添加更准确的解释。

只要您不查询其他信息,使用 GROUP BY 语句减少查询结果的数量很容易。假设您有下表“位置”。

--country-- --city--
 France      Lyon
 Poland      Krakow
 France      Paris
 France      Marseille
 Italy       Milano

现在查询

SELECT country FROM locations
GROUP BY country

将导致:

--country--
 France
 Poland
 Italy

但是,以下查询

SELECT country, city FROM locations
GROUP BY country

...在 MS SQL 中引发错误,因为您的计算机如何知道您要在“法国”右侧的字段中读取三个法国城市“里昂”、“巴黎”或“马赛”中的哪一个?

为了更正第二个查询,您必须添加此信息。一种方法是使用函数 MAX() 或 MIN(),在所有候选值中选择最大值或最小值。 MAX() 和 MIN() 不仅适用于数值,还可以比较字符串值的字母顺序。

SELECT country, MAX(city) FROM locations
GROUP BY country

将导致:

--country-- --city--
 France      Paris
 Poland      Krakow
 Italy       Milano

或者:

SELECT country, MIN(city) FROM locations
GROUP BY country

将导致:

--country-- --city--
 France      Lyon
 Poland      Krakow
 Italy       Milano

只要您可以从字母(或数字)顺序的两端选择您的值,这些函数就是一个很好的解决方案。但如果不是这样呢?让我们假设您需要一个具有特定特征的值,例如以字母“M”开头。现在事情变得复杂了。

到目前为止,我能找到的唯一解决方案是将您的整个查询放入一个子查询中,并在其中手动构建附加列:

SELECT
     countrylist.*,
     (SELECT TOP 1 city
     FROM locations
     WHERE
          country = countrylist.country
          AND city like 'M%'
     )
FROM
(SELECT country FROM locations
GROUP BY country) countrylist

将导致:

--country-- --city--
 France      Marseille
 Poland      NULL
 Italy       Milano

A
Abe Miessler
SELECT  c2.field1 ,
        field2
FROM    (SELECT DISTINCT
                field1
         FROM   dbo.TABLE AS C
        ) AS c1
        JOIN dbo.TABLE AS c2 ON c1.field1 = c2.field1

为什么没有 C alias 可以工作?在第 FROM dbo.TABLE AS C
我相信这是由于我使用了 RedGate SQLPrompt。按照我的配置方式,它总是添加别名——即使是不必要的。它在那里“以防万一”
这对我来说看起来很有希望,但它仍然带回了所有行,而不是不同的 field1。 :(
C
Community

好问题@aryaxt——你可以说这是一个好问题,因为你在 5 年前问过它,而我今天偶然发现它试图找到答案!

我只是尝试编辑接受的答案以包含此内容,但如果我的编辑未包含在:

如果您的表不是那么大,并且假设您的主键是一个自动递增的整数,您可以执行以下操作:

SELECT 
  table.*
FROM table
--be able to take out dupes later
LEFT JOIN (
  SELECT field, MAX(id) as id
  FROM table
  GROUP BY field
) as noDupes on noDupes.id = table.id
WHERE
  //this will result in only the last instance being seen
  noDupes.id is not NULL

S
Suraj Rao

尝试

SELECT table.* FROM table 
WHERE otherField = 'otherValue'
GROUP BY table.fieldWantedToBeDistinct
limit x

O
Oleg

您可以使用 WITH 子句来做到这一点。

例如:

WITH c AS (SELECT DISTINCT a, b, c FROM tableName)
SELECT * FROM tableName r, c WHERE c.rowid=r.rowid AND c.a=r.a AND c.b=r.b AND c.c=r.c

这也允许您仅选择在 WITH 子句查询中选择的行。


d
dotjoe

对于 SQL Server,您可以使用 dense_rank 和其他窗口函数来获取指定列上具有重复值的所有行和列。这是一个例子......

with t as (
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r1' union all
    select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r2' union all
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r3' union all
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r4' union all
    select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r5' union all
    select col1 = 'a', col2 = 'a', col3 = 'a', other = 'r6'
), tdr as (
    select 
        *, 
        total_dr_rows = count(*) over(partition by dr)
    from (
        select 
            *, 
            dr = dense_rank() over(order by col1, col2, col3),
            dr_rn = row_number() over(partition by col1, col2, col3 order by other)
        from 
            t
    ) x
)

select * from tdr where total_dr_rows > 1

这是对 col1、col2 和 col3 的每个不同组合进行行计数。


过于复杂且特定于 SQL 的一种实现
D
Dharman
select min(table.id), table.column1
from table 
group by table.column1

这对我有用!值得注意的是,如果您使用的是 fetch_array() ,那么您将需要通过索引标签调用每一行,而不是隐式调用行名。这里没有足够的字符让我写出我的例子:X 对不起!
我认为这只适用于mysql,不适用于postgresql
b
bluish
SELECT *
FROM tblname
GROUP BY duplicate_values
ORDER BY ex.VISITED_ON DESC
LIMIT 0 , 30

ORDER BY 我刚刚在这里放了示例,您也可以在此添加 ID 字段


如已接受的答案中所述,适用于大多数 SQL 化身——仅适用于 MYSQL
M
Michael Fever

在这里其他地方找到了这个,但这是一个有效的简单解决方案:

 WITH cte AS /* Declaring a new table named 'cte' to be a clone of your table */
 (SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY val1 DESC) AS rn
 FROM MyTable /* Selecting only unique values based on the "id" field */
 )
 SELECT * /* Here you can specify several columns to retrieve */
 FROM cte
 WHERE rn = 1

适用于 MSSQL
i
iCodeCrew

将 GROUP BY 添加到要检查重复项的字段,您的查询可能看起来像

SELECT field1, field2, field3, ......   FROM table GROUP BY field1

将检查 field1 以排除重复记录

或者你可以像这样查询

SELECT *  FROM table GROUP BY field1

从 SELECT 中排除 field1 的重复记录


GROUP BY 子句必须匹配选定的字段。否则它会抛出像 filed2 must appear in the GROUP BY clause or be used in an aggregate function 这样的错误
w
wayneh

只需在 GROUP BY 子句中包含所有字段。


为了使这是一个好的答案,您应该包含更多关于您的意思的细节。
Z
Zaheer Babar

可以通过内部查询来完成

$query = "SELECT * 
            FROM (SELECT field
                FROM table
                ORDER BY id DESC) as rows               
            GROUP BY field";

这不能回答问题,OP 试图获取表的所有数据,但删除包含单个字段重复项的行
A
Andrew
SELECT * from table where field in (SELECT distinct field from table)

那是行不通的。您在子查询中选择了不同的列,但 where 子句获取所有具有该值的列。因此,查询与编写“select * from table”一样好,除非“field”列是唯一列,在这种情况下,根本不需要该列上的 distinct。
D
Doris Gammenthaler

如果所有三列的值在表中都是唯一的,则 SELECT DISTINCT FIELD1, FIELD2, FIELD3 FROM TABLE1 有效。

例如,如果名字有多个相同的值,但所选列中的姓氏和其他信息不同,则该记录将包含在结果集中。


这不能回答问题,OP 试图获取表的所有数据,但删除包含单个字段重复项的行
J
JJJ

我建议使用

SELECT  * from table where field1 in 
(
  select distinct field1 from table
)

这样,如果您在 field1 中的多行具有相同的值,则将返回所有记录。


SELECT * FROM table; 没有什么不同。甚至更慢。
请先试试你的答案。