2017-05-17 12 views
0

MS SQL Serverで、最大5つの電子メールアドレスフィールドを取得し、それらを1つのEmailAddressesフィールドに連結するビューを作成しています。それは簡単な部分です。そのトリックは、結果の文字列が100文字を超えることはできず、私たちは部分的なメールアドレスを必要としないので、私はちょうどCONCATとLEFT(EmailAddresses、100)を行うことはできません。文字列は電子メールアドレスで終わり、の前に100文字の制限を超える文字列が必要です。SQLで特定の長さまでCONCATをうまく処理する方法

私は今それをやっている方法は、ケース付きです。

SELECT CASE WHEN LEN(Email1 + IsNull(';' + Email2, '') + IsNull(';' + Email3, '') + IsNull(';' + Email4, '')) <= 100 
      THEN Email1 + IsNull(';' + Email2, '') + IsNull(';' + Email3, '') + IsNull(';' + Email4, '') 
     WHEN LEN(Email1 + IsNull(';' + Email2, '') + IsNull(';' + Email3, '')) <= 100 
      THEN Email1 + IsNull(';' + Email2, '') + IsNull(';' + Email3, '') 
     WHEN LEN(Email + IsNull(';' + Email2, '')) <= 100 
      THEN Email + IsNull(';' + Email2, '') 
     ELSE Email1 
    END as Email_Address 

これは実際にはうまく動作しますが、それは醜いです。このような状況に近づくよりエレガントな方法はありますか?

+1

何rdbms? SQLサーバー? – SQLChao

+0

SQL Server、はい。それが無効であれば、気にしていないようです。うまくいきます。 :)私はそれ以降のケースについては、MSのドキュメントからフォーマットを得ました。 –

答えて

1

これらの例は、SQL Server 2012の

declare @T table (id int identity(1,1), email1 varchar(80), email2 varchar(80), email3 varchar(80), email4 varchar(80)); 

insert into @T (email1,email2,email3,email4) values 
('[email protected]','[email protected]','[email protected]','[email protected]'), 
('[email protected]',null,'[email protected]',null), 
('[email protected]','[email protected]','[email protected]','[email protected]'); 


select id, 
concat(
max(case when n=1 then m end), 
max(case when n=2 then ';'+m end), 
max(case when n=3 then ';'+m end), 
max(case when n=4 then ';'+m end) 
) as emails 
from 
(
select id, n, m, sum(len(m)+1) over (partition by id order by n ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as RunningTotal 
from @T t0 
cross apply (values (1,email1),(2,email2),(3,email3),(4,email4)) mails(n,m) 
) q 
where RunningTotal <= 100 
group by id; 

またはXMLトリックを使用して動作します:

select id, 
STUFF((select ';'+m 
from 
(
    select m, sum(len(m)+1) over (partition by id order by n ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as RunningTotal 
    from @T t0 
    cross apply (values (1,email1),(2,email2),(3,email3),(4,email4)) q(n,m) 
    where t0.id = t.id 
) q 
where RunningTotal <= 100 
FOR XML PATH ('') 
),1,1,'') as mails 
from @T t 
group by id; 

やケース、連結、左、CHARINDEXと逆を使用して(?少なくとも '醜いです') :

select id, 
(case 
when len(emails)>100 
then left(left(emails,101-charindex(';',reverse(left(emails,101)))),100) 
else emails 
end) as emails 
from (
    select id, concat(email1,';'+email2,';'+email3,';'+email4) as emails 
    from @T 
) q; 

おそらくこれは?

select id, 
concat(email1, 
     case when isnull(len(email1),0)+isnull(len(email2)+1,0) <= 100 then ';'+email2 end, 
     case when isnull(len(email1),0)+isnull(len(email2)+1,0)+isnull(len(email3)+1,0) <= 100 then ';'+email3 end, 
     case when isnull(len(email1),0)+isnull(len(email2)+1,0)+isnull(len(email3)+1,0)+isnull(len(email4)+1,0) <= 100 then ';'+email4 end 
    ) as emails 
from @T; 
+0

私は決して眺めが好きではありませんでした。興味深いアプローチ。 –

+0

@JasonJacobsビューでは、サブクエリのレベルが2つ以上あると思いますか?とにかく、もう2つの方法を追加しました。おそらく3番目のものが最も「醜い」ものです。 – LukStorms

1

私が提案しようとしているのは恐ろしいことです。しかし、の代替品です。すべての電子メール

  • は、長さ(あなたがカットする場所をマーキング)最初のセミコロンを見つけるために
  • rtrimを一番左の100文字
  • reverse文字列
  • strposを取る

    1. 、連結方式 - strpos from(4)
    2. reverseもう一度文字列
  • +0

    私はあなたがレッドシフトにいると仮定しています。あなたがいるなら、あなたはPythonを介してユーザ定義関数を構築することもできます。 – ScottieB

    +0

    それは奇妙な前提です。 SQL Serverのように見えます。 – Donnie

    関連する問題