不同的SQL查询

时间:2009-03-03 05:16:14

标签: sql

我有一个简单的表,只有名称和电子邮件名为name_email。

我正在尝试从中获取数据,以便: 如果两行具有相同的名称,但其中一行的电子邮件以“@ yahoo.com”结尾,而另一行的电子邮件不同,则电子邮件将带有“@ yahoo.com”电子邮件应该被丢弃。

什么是获取此数据的最佳方式?

8 个答案:

答案 0 :(得分:3)

好吧,我不打算再和那些说我不应该提倡数据库架构更改的人打架(是的,你知道你是谁:-),但这就是我要做的。

1 /如果你绝对不能改变架构,我会用代码解决它(在数据库之外的真实诚实的程序代码或者你的DBMS允许的任何语言的存储过程)。

这会检查数据库中是否有非雅虎名称并返回它,如果有的话。如果没有,它将尝试返回雅虎名称。如果两者都没有,它将返回一个空数据集。

2 /如果您可以更改架构,并且希望SQL查询完成工作,那么我就是这样做的。在表中创建一个名为CLASS的单独列,对于非yahoo地址,应该设置为0,对于yahoo地址,设置为1。

创建插入/更新触发器以检查每行的添加或更改,根据电子邮件地址(结束的内容)设置CLASS。这可以保证CLASS始终正确设置。

查询表格时,按名称和类别排序,只选择第一行。这将为您提供以下首选项的电子邮件地址:非雅虎,雅虎,空数据集。

类似的东西:

select name, email
from tbl
where name = '[name]'
order by name, class
fetch first row only;

如果您的DBMS没有等同于DB2“fetch first row only”子句,您可能仍需要编写代码来处理一条记录。

如果你想处理所有名称,但只处理该名称所需的特定电子邮件,那么这样的程序就足够了(我试图以程序方式使用SQL等关系代数的观点非常残酷,所以我不会在这里对你施加伤害):

# Get entire table contents sorted in name/class order.
resultSet = execQuery "select name, email from tbl order by name, class"

# Ensure different on first row
lastName = resultSet.value["name"] + "X"

# Process every single row returned.
while not resultSet.endOfFile:
    # Only process the first in each name group (lower classes are ignored).
    if resultSet.value["name"] != lastName:
        processRow resultSet.value["name"] resultSet.value["email"]
    # Store the last name so we can detect next name group.
    lastName = resultSet.value["name"]

答案 1 :(得分:1)

select ne.*
from name_email ne
where ne.email not like '%@yahoo.com' escape '\' or
    not exists(
               select 1 from name_email
               where name = ne.name and
               email not like '%@yahoo.com' escape '\'
              )

答案 2 :(得分:0)

您可以使用以下内容排除无效的电子邮件地址:

SELECT name, email
FROM name_email
WHERE email NOT LIKE '%@yahoo.com' // % symbol is a wildcard so joe@yahoo.com and guy@yahoo.com both match this query.
AND name = 'Joe Guy';

或者这样做只包含有效的电子邮件地址或域名:

SELECT name, email
FROM name_email
WHERE email LIKE '%@gmail.com'
AND name = 'Joe Guy';

如果您提前知道要查询的具体名称以及要排除或包含的电子邮件地址或域名,则此方法很有效。

或者,如果您不关心您返回的电子邮件地址,但只想返回一个,您可以使用以下内容:

SELECT DISTINCT (name, email)
FROM name_email;

答案 3 :(得分:0)

你可以做到

SELECT TOP 1 email
FROM name_email
WHERE name = 'Joe Guy'
ORDER BY case when email like '%yahoo.com' then 1 else 0 end

因此,请先将* @yahoo.com排序,然后再将其他任何内容排序,然后选择第一个。

编辑:抱歉,误读了这个问题 - 你想要一个每个名字的列表,只有一封电子邮件,以及非雅虎电子邮件的偏好。可能可以使用上面的一组,我将不得不重新考虑它。

答案 4 :(得分:0)

从数据库中抓取所有行,不知道名称是什么(并且不需要真正关心它),但只是希望它们显示,如果匹配,则跳过匹配,如果电子邮件包含,在这种情况下, @ yahoo.com

SELECT DISTINCT name, email FROM name_email 
  WHERE email NOT LIKE '%@yahoo.com' 
  GROUP BY name;

执行该操作将获取所有行,但只有一个记录,如果名称与另一行匹配。但是,如果有两行具有匹配的名称,则在电子邮件中使用 @ yahoo.com 进行垃圾处理。

答案 5 :(得分:0)

不是很漂亮,但我相信它应该有效

select 
    ne.name 
    ,ne.email
from 
    name_email ne
    inner join (
        select 
            name 
            ,count(*) as emails_per_name
        from 
            name_email
        group by name
    ) nec 
        on ne.name = nec.name
where
    nec.emails_per_name = 1
    or (nec.emails_per_name > 1 and ne.email not like ('%@yahoo.com'))

假设重复的电子邮件将在yahoo.com域中 - 如您的问题中所指定的那样,如果每个名称有多个电子邮件,则会排除这些电子邮件

答案 6 :(得分:0)

如果您正在使用SQL Server 2005或Oracle,则可以使用排名(分析)功能轻松解决您的问题。

select a.name, a.name_email
from (select name, name_email,
             row_number() over (partition by name
                                order by case
                                           when name_email like '%@yahoo.com' then 1
                                           when name_email like '%@gmail.com' then 1
                                           when ... (other 'generic' email) then 1
                                           else 0
                                         end) as rn) as a
where a.rn = 1

通过为各种通用电子邮件名称指定不同的值,您甚至可以拥有“首选项”。正如这里所写,如果你同时拥有雅虎和gmail地址,你无法预测哪一个会被接收。

答案 7 :(得分:0)

你可以使用UNION。选择没有yahoo.com的所有内容,然后只选择具有yahoo.com且不在第一个列表中的记录。

SELECT DISTINCT(name,name_email)FROM TABLE 在哪里name_email不'%yahoo.com' 联盟 SELECT DISTINCT(name,name_email)FROM TABLE WHERE name NOT IN(SELECT DISTINCT(name,name_email)FROM TABLE 如果name_email不是'%yahoo.com')