質問

では、以下のテーブルSQL Server2005年

ID   Col1   Col2   Col3
--   ----   ----   ----
1       3     34     76  
2      32    976     24
3       7    235      3
4     245      1    792

どのようにクエリの利回り以下の結果(る利回りは、最終column-カラムを含むminium値のCol1,Col2、コ3 各行)?

ID   Col1   Col2   Col3  TheMin
--   ----   ----   ----  ------
1       3     34     76       3
2      32    976     24      24
3       7    235      3       3
4     245      1    792       1

更新:

のための明確化(これまでも述べてきたようにコメントを登録)のシナリオのデータベース 適切に正規化され.これらの"配列"カラムは実際のテーブルは結果セットに必要なレポートを提出します。に新しいことを確認する必要があり、報告書もこのMinValueます。できない変更を配下の結果セットしたT-SQLのためのハンディ"の刑務所です。

またアプローチの場合は、下記動作することがあ常に煩雑です。それはとても複雑で、記載の回答のために必要な対応は、ここ半年間の間、ある分値と同じです。

とにかく、ながらよく集めたものだと思うの後現在のソリューションは、私の制約の作品ですね。このUNPIVOTオペレーター:

with cte (ID, Col1, Col2, Col3)
as
(
    select ID, Col1, Col2, Col3
    from TestTable
)
select cte.ID, Col1, Col2, Col3, TheMin from cte
join
(
    select
        ID, min(Amount) as TheMin
    from 
        cte 
        UNPIVOT (Amount for AmountCol in (Col1, Col2, Col3)) as unpvt
    group by ID
) as minValues
on cte.ID = minValues.ID

思先ることはないと思いこのプロジェクトが新たなフェーズがそのような状況下にしていったんでリデザインのすべてのクエリーだけの新しいMinValueカラムの要件でもかわいらしいエレガント"の刑務所です。

役に立ちましたか?

解決

これを達成するための多くの方法である可能性が高いがあります。私の提案は、/ときにそれを行うためにケースを使用することです。 3列で、それはあまりにも悪くはありません。

Select Id,
       Case When Col1 < Col2 And Col1 < Col3 Then Col1
            When Col2 < Col1 And Col2 < Col3 Then Col2 
            Else Col3
            End As TheMin
From   YourTableNameHere

他のヒント

CROSS APPLYを使用します:

SELECT ID, Col1, Col2, Col3, MinValue
FROM YourTable
CROSS APPLY (SELECT MIN(d) MinValue FROM (VALUES (Col1), (Col2), (Col3)) AS a(d)) A

SQLフィドルする

SELECT ID, Col1, Col2, Col3, 
    (SELECT MIN(Col) FROM (VALUES (Col1), (Col2), (Col3)) AS X(Col)) AS TheMin
FROM Table

あなたは、ひねりを加えた「ブルートフォース」アプローチを使用することができます:

SELECT CASE
    WHEN Col1 <= Col2 AND Col1 <= Col3 THEN Col1
    WHEN                  Col2 <= Col3 THEN Col2
    ELSE                                    Col3
END AS [Min Value] FROM [Your Table]

また、第1の条件が失敗したときにそれはのCol1はあなたが条件の残りの部分からそれを排除することができますので、最小値ではないことを保証します。同様に、後続の条件について。 5列の場合、あなたのクエリになります:

SELECT CASE
    WHEN Col1 <= Col2 AND Col1 <= Col3 AND Col1 <= Col4 AND Col1 <= Col5 THEN Col1
    WHEN                  Col2 <= Col3 AND Col2 <= Col4 AND Col2 <= Col5 THEN Col2
    WHEN                                   Col3 <= Col4 AND Col3 <= Col5 THEN Col3
    WHEN                                                    Col4 <= Col5 THEN Col4
    ELSE                                                                      Col5
END AS [Min Value] FROM [Your Table]

2つの以上の列間のタイがある場合、その後<=は、我々は可能な限り早期にCASE文を終了することを保証することに注意してください。

それを行うための最善の方法はそれを行うには、おそらく、のないのです - 人々は遠くがある場合には、意味のある情報を抽出するために、SQL「体操」が必要な方法で自分のデータを格納することを主張することを奇妙ですあなたは自分のスキーマが少し良く構造化する場合には、望ましい結果を達成するための簡単な方法: - )

これを行うには、

の右のの方法で、私の意見では、次の表を持つことです。

ID    Col    Val
--    ---    ---
 1      1      3
 1      2     34
 1      3     76

 2      1     32
 2      2    976
 2      3     24

 3      1      7
 3      2    235
 3      3      3

 4      1    245
 4      2      1
 4      3    792

(必要に応じて、そしておそらくID/Col余分なキーとして、)主キーとしてColと。次に、あなたのクエリは、単純なselect min(val) from tblになり、あなたはまだ他のクエリでwhere col = 2を使用して、個々の「古い列」別に扱うことができます。 「古いカラムの数が成長する必要がありこれも簡単に拡張することができます。

これはあなたのクエリがのようにの方がはるかに簡単になります。あなたがを場合、私は使用する傾向がある一般的なガイドラインは、あるかつてのデータベース列の配列のようなものを持っている、あなたはおそらく何か間違ったことをやっているし、データの再構築を考える必要があります。

<時間>

ただし、を何らかの理由で場合は、のこれらの列を変更することはできません、私は挿入と更新のトリガーを使用することをお勧めし、これらのトリガーが設定され、の他の列を追加したいですCol1/2/3で最小。私の経験ではほとんどのデータベース・テーブルがはるかに頻繁にその書き込みにコストをかけ書かれたよりも読み時間をかけて、より効率的になる傾向があるされている - これは、それが属する更新/挿入に離れ選択からの操作の「コスト」を移動します。

他の列のいずれかが変更されたときにつまり、行の最小は唯一の変更なので、はそれです。のあなたはそれを計算しなければならないとき、データあれば無駄になっているあなたが選択していないたびに( )変更されていません。

:あなたは、その後のようなテーブルで終わるだろう
ID   Col1   Col2   Col3   MinVal
--   ----   ----   ----   ------
 1      3     34     76        3
 2     32    976     24       24
 3      7    235      3        3
 4    245      1    792        1
別の列を追加するには、DBに多くのスペースを占め、少し遅くなります - データのみを挿入/更新に変化するため、

select時の意思決定を行うために持っている他のオプションは、通常は悪いアイデアのパフォーマンスが賢明です挿入および更新のためのが、の多くのの速い選択のためにすることができます - 述べ、ほとんどのテーブルは、のはるかのより多くの場合よりも読まれるよう好ましいアプローチは、そこにあなたの優先順位に依存するが必要があります書かれた「再ます。

私は、関数を作成し、あなたの例のように列が整数だった場合:

create function f_min_int(@a as int, @b as int) 
returns int
as
begin
    return case when @a < @b then @a else coalesce(@b,@a) end
end

私はそれを使用する必要がある場合、私はどうなるます:

select col1, col2, col3, dbo.f_min_int(dbo.f_min_int(col1,col2),col3)

あなたは5つのcolumsを持っているならば、上記になる。

select col1, col2, col3, col4, col5,
dbo.f_min_int(dbo.f_min_int(dbo.f_min_int(dbo.f_min_int(col1,col2),col3),col4),col5)

これを使用します:

select least(col1, col2, col3) FROM yourtable

また、ユニオンクエリでこれを行うことができます。列の数が増加するにつれて、クエリを変更する必要があるだろうが、少なくともそれはまっすぐ前方変更となります。

Select T.Id, T.Col1, T.Col2, T.Col3, A.TheMin
From   YourTable T
       Inner Join (
         Select A.Id, Min(A.Col1) As TheMin
         From   (
                Select Id, Col1
                From   YourTable

                Union All

                Select Id, Col2
                From   YourTable

                Union All

                Select Id, Col3
                From   YourTable
                ) As A
         Group By A.Id
       ) As A
       On T.Id = A.Id

このは強引ですが、動作します。

 select case when col1 <= col2 and col1 <= col3 then col1
           case when col2 <= col1 and col2 <= col3 then col2
           case when col3 <= col1 and col3 <= col2 then col3
    as 'TheMin'
           end

from Table T

...分は()1列のみではなく列にわたって動作しますので。

この質問この質問 答えいただく。

をおさらいはOracleには、内蔵機能のために、Sqlサーバーでこだわったどちらかを定義するユーザ定義関数の使用の場合ます。

ストアドプロシージャを作ることができるしている場合は、

は、値の配列を取ることができる、あなたはちょうどそれを呼び出すことができます。

select *,
case when column1 < columnl2 And column1 < column3 then column1
when columnl2 < column1 And columnl2 < column3 then columnl2
else column3
end As minValue
from   tbl_example

ユニオンクエリに少しひねります:

DECLARE @Foo TABLE (ID INT, Col1 INT, Col2 INT, Col3 INT)

INSERT @Foo (ID, Col1, Col2, Col3)
VALUES
(1, 3, 34, 76),
(2, 32, 976, 24),
(3, 7, 235, 3),
(4, 245, 1, 792)

SELECT
    ID,
    Col1,
    Col2,
    Col3,
    (
        SELECT MIN(T.Col)
        FROM
        (
            SELECT Foo.Col1 AS Col UNION ALL
            SELECT Foo.Col2 AS Col UNION ALL
            SELECT Foo.Col3 AS Col 
        ) AS T
    ) AS TheMin
FROM
    @Foo AS Foo

あなたはSQL 2005を使用している場合は、このようなきちんとした何かを行うことができます:

;WITH    res
          AS ( SELECT   t.YourID ,
                        CAST(( SELECT   Col1 AS c01 ,
                                        Col2 AS c02 ,
                                        Col3 AS c03 ,
                                        Col4 AS c04 ,
                                        Col5 AS c05
                               FROM     YourTable AS cols
                               WHERE    YourID = t.YourID
                             FOR
                               XML AUTO ,
                                   ELEMENTS
                             ) AS XML) AS colslist
               FROM     YourTable AS t
             )
    SELECT  YourID ,
            colslist.query('for $c in //cols return min(data($c/*))').value('.',
                                            'real') AS YourMin ,
            colslist.query('for $c in //cols return avg(data($c/*))').value('.',
                                            'real') AS YourAvg ,
            colslist.query('for $c in //cols return max(data($c/*))').value('.',
                                            'real') AS YourMax
    FROM    res

あなたは非常に多くの事業者で迷子にしないでください。この方法:)

しかし、これは他の選択肢よりも遅くなる可能性があります。

それはあなたの選択です...

以下を使用してい温度テーブルの最小の数。最初の温度テーブルのクエリに複数テーブルを取得しないんだろうなどその他の値は、クエリ)の温度テーブルを取得し、各列の最小の日付として利用して多くの経過が日列あります。

これは基本的には同盟のクエリと同じ数のパスが必要な場合の効率化に基づく経験が必要とする効率な問題の場合(8,000録)を保持することになる。この指数等

--==================== this gets minimums and global min
if object_id('tempdb..#temp1') is not null
    drop table #temp1
if object_id('tempdb..#temp2') is not null
    drop table #temp2

select r.recordid ,  r.ReferenceNumber, i.InventionTitle, RecordDate, i.ReceivedDate
, min(fi.uploaddate) [Min File Upload], min(fi.CorrespondenceDate) [Min File Correspondence]
into #temp1
from record r 
join Invention i on i.inventionid = r.recordid
left join LnkRecordFile lrf on lrf.recordid = r.recordid
left join fileinformation fi on fi.fileid = lrf.fileid
where r.recorddate > '2015-05-26'
 group by  r.recordid, recorddate, i.ReceivedDate,
 r.ReferenceNumber, i.InventionTitle



select recordid, recorddate [min date]
into #temp2
from #temp1

update #temp2
set [min date] = ReceivedDate 
from #temp1 t1 join #temp2 t2 on t1.recordid = t2.recordid
where t1.ReceivedDate < [min date] and  t1.ReceivedDate > '2001-01-01'

update #temp2 
set [min date] = t1.[Min File Upload]
from #temp1 t1 join #temp2 t2 on t1.recordid = t2.recordid
where t1.[Min File Upload] < [min date] and  t1.[Min File Upload] > '2001-01-01'

update #temp2
set [min date] = t1.[Min File Correspondence]
from #temp1 t1 join #temp2 t2 on t1.recordid = t2.recordid
where t1.[Min File Correspondence] < [min date] and t1.[Min File Correspondence] > '2001-01-01'


select t1.*, t2.[min date] [LOWEST DATE]
from #temp1 t1 join #temp2 t2 on t1.recordid = t2.recordid
order by t1.recordid

複数の列、その最高の2つの数値列に対してただし、CASE文を使用するにはi、jは、あなたが簡単な数学を使用することができます:

分(I、J)=(iはJ +)/ 2 - ABS(I-J)/ 2

この式は、複数の列の最小値が、その本当に厄介過去2分間(I、J、K)があろう分を取得するために使用することができる(I、分(J、K))

SELECT [ID],
            (
                SELECT MIN([value].[MinValue])
                FROM
                (
                    VALUES
                        ([Col1]),
                        ([Col1]),
                        ([Col2]),
                        ([Col3])
                ) AS [value] ([MinValue])
           ) AS [MinValue]
FROM Table;
あなたは通常、ステータスコード、探しているもの値がわかっている場合は、

は、以下を参考にすることができます:

select case when 0 in (PAGE1STATUS ,PAGE2STATUS ,PAGE3STATUS,
PAGE4STATUS,PAGE5STATUS ,PAGE6STATUS) then 0 else 1 end
FROM CUSTOMERS_FORMS

私はその質問が古いですけど、私は答えを必要とまだあったと私は@ paxdiablo's <のhref = "httpsの上のねじれである自分自身を考案しなければならなかったので、他の回答に満足できませんでした。 //stackoverflow.com/a/368394/3336667">answerするます。

<時間>

私は、SAP ASE 16.0の土地から来た、と私は私見有効に単一の行の異なる列に格納されている特定のデータの統計で覗いて必要な(彼らは異なる時間を表す - 何かの到着は何それ、計画されたときアクションが開始され、最終的には実際の時間だったかと)期待されました。したがって、私は、一時テーブルの行に列を転置し、通常のように、この上で、私のクエリを予め形成していました。

N.B。先の未フリーサイズ解決!

CREATE TABLE #tempTable (ID int, columnName varchar(20), dataValue int)

INSERT INTO #tempTable 
  SELECT ID, 'Col1', Col1
    FROM sourceTable
   WHERE Col1 IS NOT NULL
INSERT INTO #tempTable 
  SELECT ID, 'Col2', Col2
    FROM sourceTable
   WHERE Col2 IS NOT NULL
INSERT INTO #tempTable 
  SELECT ID, 'Col3', Col3
    FROM sourceTable
   WHERE Col3 IS NOT NULL

SELECT ID
     , min(dataValue) AS 'Min'
     , max(dataValue) AS 'Max'
     , max(dataValue) - min(dataValue) AS 'Diff' 
  FROM #tempTable 
  GROUP BY ID

これは、タイムクリティカルなプロセスではなく、1回のデータ検査や終わりの日のレポートのようなもののために実行する事63万行のソースセットにいくつかの30秒を要しただけインデックス・データを使用し、そうではありませんあなたは(、してくださいしかし、あなたの同僚や上司とこれを確認!)細かいかもしれません。 このスタイルの主なボーナスは、の私のためのの私は容易にデータがオーバーcopyiedた特に一度、より多く/少なく列と変更のグループ化、フィルタリングなどを使用するということでした。

追加データ(columnNamemaxes、...)あなたがそれらを必要としない場合がありますので、私の検索で私を助けることでした。私は多分いくつかのアイデアを刺激するためにそれらをここに左: - 。)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top