2012-04-02 11 views
2

私は、複数のビューを作成している非常に大きなスクリプトを持っています。多くのビューでは、同じスクリプトが使用されています。このスクリプトは以下の通りです。SQLのcase文をストアドプロシージャに変換しますか?

CASE WHEN pc.[user_name] IN 
(
    SELECT [user_name] 
    FROM people AS p WITH(NOLOCK) 
    WHERE p.status_id = 1 p.last_login > DATEADD(MONTH, -12, GETDATE()) 
    AND p.[user_name] NOT IN 
    (
     SELECT p.[user_name] 
     FROM people AS p WITH(NOLOCK) 
     WHERE p.status_id IN (1,2) AND p.[user_name] LIKE '%2' 
    ) 
) THEN pc.[user_name] 
ELSE 'standarduser' END AS created_by 

誰かが私がpc.[user_name]に渡すことができ、それが正しい値を返す関数を作成する方法の正しい方向に私を指すもらえますか?私はSQLで新しい関数です。ありがとうございました。

+4

どのDBを使用していますか? –

+2

うわー...結果セットでこの関数を使用すると、あなたのクエリはslooooowになります... –

+0

user_nameの代わりにチェックできる主キーがありませんか? – Arion

答えて

2

のように参加しました:

私はUSER_NAMEは、1と2のSTATUS_ID両方を持つことができない。すなわち、これは私が声明から NOT INを削除することができ、USER_NAMEが一意であるという仮定に基づいて、可能な限り、あなたの選択を簡素化しようとしてい
CREATE FUNCTION [dbo].[FunctionName] (@UserName VARCHAR(50)) 
RETURNS VARCHAR(50) 
AS 
BEGIN 
    RETURN COALESCE(
       ( SELECT [User_name] 
        FROM people AS p WITH(NOLOCK)  
        WHERE p.status_id = 1 
        AND  p.last_login > DATEADD(MONTH, -12, GETDATE())  
        AND  p.[user_name] NOT LIKE '%2' 
        AND  [User_name] = @UserName 
       ), 'StandardUser') 
END 

最初にstatus_IDが1のユーザグループを選択し、status_IDが1または2で、ユーザ名が2で終わるものを削除します。最初のグループにstatus_IDを持たない誰も存在しないため1の場合は、ユーザー名が2で終わる最初のグループのサブクエリを削除することができます。サブクエリは不要で、where句だけは必要ありません。

これまで述べてきたように、私は同じような結果を得るためにビューや同様のセットベースのソリューションを使用する傾向があります。次のようなもの:

SELECT *, COALESCE(a.[User_Name], 'StandardUser') [NewUserName] 
FROM People p 
     LEFT JOIN 
     ( SELECT [User_name] 
      FROM people AS p WITH(NOLOCK)  
      WHERE p.status_id = 1 
      AND  p.last_login > DATEADD(MONTH, -12, GETDATE())  
      AND  p.[user_name] NOT LIKE '%2' 
     ) a 
      ON p.[User_name] = a.[User_name] 
+0

Garethに感謝します。あなたが与えたアドバイスを使って、私はうまくいけば質問時間を減らすことができるでしょう。ビューや関数を使う方が良いと思いますか? –

+0

パフォーマンスが問題になる場合は、スカラー関数を使用せずに、表関数を使用してください。 – JeffO

+0

ビュー。原則として、可能な限りスカラー関数を避けるようにしています。これらはうまく最適化されておらず、udfs over setベースのソリューションを使用すると、パフォーマンスが大幅に低下することに気付くでしょう。最も単純なudfでさえパフォーマンスに影響を与えることができるかどうかの非常に素晴らしいデモンストレーション[here](http://www.sql-server-performance.com/2005/sql-server-udfs/)があります。 – GarethD

0

[編集]この

CREATE function [dbo].[MyFunction] (
@UserName nvarchar 
) 
returns nvarchar 
as 
begin 
CASE WHEN pc.[user_name] IN 
(  
    SELECT [user_name]  
    FROM people AS p WITH(NOLOCK)  
    WHERE p.status_id = 1 p.last_login > DATEADD(MONTH, -12, GETDATE())  

    AND p.[user_name] NOT IN 
    (   
     SELECT p.[user_name]   
     FROM people AS p WITH(NOLOCK)   
     WHERE p.status_id IN (1,2) AND p.[user_name] LIKE '%2'  
    ) 
) 
THEN pc.[user_name] ELSE 'standarduser' END AS created_by 

end 

GO 

のようにスカラー値関数を試みることができる: ああ、あなたは

+0

私は上記のコメントに同意しますが、私はコピーし、あなたのクエリを関数に貼り付けました。選択した部分が機能するようになったら、[user_name]を[user_id]に変更するか、そのテーブルのIDが何であっても切り替える必要があります。 "IN"リストでintをチェックするほうがはるかに効率的です –

0

であるSQL Serverを使用しているあなたは、このビューまたは表関数(もしあなた作ることができると仮定すると次のようにothereロジックを必要とするか、パラメータを渡したい)と他のビューに含める/ procsのは、関数を作成することができ、テーブル

; 
with users as (
select p.user_name 
    , p.status_id 
    , p.last_login 
from people as p with(nolock) 
where p.status_id IN (1,2) 
) 
select DISTINCT u.user_name 
    , CASE WHEN u.[user_name] IN 
    ( 
     SELECT [user_name] 
     FROM users AS u1 
     WHERE u1.status_id = 1 u1.last_login > DATEADD(MONTH, -12, GETDATE()) 
     AND u1.[user_name] NOT IN 
      ( 
      SELECT u2.[user_name] 
      FROM users AS u2 
      WHERE u2.status_id IN (1,2) AND u2.[user_name] LIKE '%2' 
     ) 
    ) THEN u.[user_name] 
     ELSE 'standarduser' END AS created_by 
from users as u 
関連する問題