2009-03-03 4 views
0

У меня есть простая таблица с именем и адресом электронной почты, называемым name_email.отличный sql-запрос

Я пытаюсь получить данные из него так, что: Если две строки имеют такое же имя, но один имеет электронную почту, которая заканчивающуюся «@ yahoo.com», а другой имеет другой адрес электронной почты, то тот, который с адресом @ @ yahoo.com должен быть отброшен.

Какой был бы лучший способ получить эти данные?

ответ

3

Хорошо, я не собираюсь участвовать в еще одном бою с теми, кто говорит, что я не должен защищать изменения схемы базы данных (да, вы знаете, кто вы такой :-), но вот как я это сделаю ,

1/Если вы абсолютно не можете изменить схему, я бы разрешил ее с помощью кода (либо реального честного, либо добротного процедурного кода вне базы данных, либо как хранимую процедуру на любом языке, который разрешает ваша СУБД).

Это проверит базу данных для имени, отличного от yahoo, и вернет его, если есть. Если нет, он попытается вернуть имя yahoo. Если их нет, он вернет пустой набор данных.

2/Если вы можете изменить схему и хотите, чтобы SQL-запрос выполнял работу, вот как бы я это сделал. Создайте отдельный столбец в таблице, называемый CLASS, который, как ожидается, будет установлен в 0 для адресов, отличных от yahoo, и 1 для адресов yahoo.

Создайте триггеры вставки/обновления, чтобы изучить каждое добавление или изменение строки, задав КЛАСС на основе адреса электронной почты (с чего он заканчивается). Это гарантирует, что CLASS всегда будет правильно настроен.

Когда вы запрашиваете свою таблицу, закажите ее по имени и классу и выберите только первую строку. Это даст вам адрес электронной почты в следующем предпочтении: non-yahoo, yahoo, пустой набор данных.

Что-то вроде:

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

Если СУБД не имеют эквивалента в DB2 «выборки первой строки только» положение, вы, вероятно, все равно придется писать код только один процесс записи.

Если вы хотите обработать все имена, но только специальное письмо для этого имени, такой программы будет достаточно (мои взгляды на попытку использовать реляционную алгебру, такую ​​как 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"] 
+0

Это правильный способ решить эту проблему. – kquinn

0

Вы можете использовать что-то вроде следующих исключить недействительных адресов электронной почты:

SELECT name, email 
FROM name_email 
WHERE email NOT LIKE '%@yahoo.com' // % symbol is a wildcard so [email protected] and [email protected] 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; 
+0

это вещь. Я не знаю имена раньше времени :) Я ищу дубликаты имен. – Omnipresent

+0

Будет ли второй работать лучше с помощью оператора DISTINCT? –

+0

Если у вас есть дополнительные критерии, например, каждое имя, имеющее два адреса электронной почты, должно всегда возвращать x адрес электронной почты, тогда отредактируйте свой вопрос, чтобы это отразить. –

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 

Так сортировать их by *@yahoo.com last и что-то еще в первую очередь, и возьмите первый.

EDIT: извините, неверно сформулируйте вопрос - вы хотите, чтобы список каждого имени имел только одно электронное письмо и предпочтение для электронных писем, отличных от yahoo. Возможно, вы можете использовать вышеупомянутое вместе с группой, мне придется переосмыслить его.

+0

Это сработает, но я не большой поклонник обработки на каждой строке. Это то, что нужно сделать, используя отдельный столбец и триггеры. Большинство таблиц в моем опыте читаются гораздо чаще, чем написано. Процесс установки вставки/обновления для настройки порядка сортировки лучше IMNSHO :-). – paxdiablo

+0

Это связано с моим мэйнфреймом, где даже наши таблицы конфигурации затмевают таблицы транзакций этих «меньших» баз данных :-) – paxdiablo

0

Схватив все строки из базы данных, не зная, какие имена (и не нуждаясь заботиться о том, что на самом деле), но просто хочу, чтобы показать, и если сопоставление, пропустите совпадение, если в нем содержится письмо, в данном случае @ yahoo.com

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

Выполнение этого будет захватывать все строки, но только одну запись, если имена совпадают с другой строкой. Но тогда, если есть две строки с совпадающими именами, напишите файл с @ yahoo.com по электронной почте.

+0

Если вы группируете имя по имени, то вам нужно будет иметь агрегатную функцию, например min (email) Кроме того, я считаю, что если у человека есть только одно электронное письмо, и это электронная почта yahoo, он хочет, чтобы он вернулся. Это только если есть дубликаты, и один из них - это то, что он хочет другого. – MikeW

+0

OPQ читает, как будто он хочет захватить все разные строки на основе имени, которое он не знает заранее. В случае строки с тем же именем хочет проверить, какие электронные письма они используют. Если кто-то из них с yahoo.com, то, чтобы вырезать это и показать не-Yahoo. – random

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 '\' 
      ) 
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 - как указано в вашем вопросе, и тех, кто будет исключен если на имя более одного электронного адреса

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 

Присвоение различных значений различным общим именам электронной почты может иметь даже «предпочтения». Как написано здесь, если у вас есть как yahoo, так и адрес gmail, вы не можете предсказать, какой из них будет выбран.

0

Для этого вы можете использовать UNION. Выберите все без yahoo.com, а затем просто выберите записи, которые имеют yahoo.com и не входят в первый список.

SELECT DISTINCT (имя, name_email) FROM TABLE ГДЕ name_email НЕ '% yahoo.com' СОЕДИНЕНИЕ SELECT DISTINCT (имя, name_email) FROM TABLE где имя НЕ В (SELECT DISTINCT (имя, name_email) FROM TABLE WHERE name_email NOT '% yahoo.com')

Смежные вопросы