11

SQL Server から 12 か月の名前を表示したい。月の名前を一時テーブルに挿入し、そのテーブルでselectステートメントを実行する必要があります。そのため、12 か月の名前を挿入するには、12 の挿入テーブルを作成する必要がありました。だから私はグーグルを検索してより良い解決策を見つけ、それを手に入れました。

これがSQLステートメントです

WITH R(N) AS
(
    SELECT 0
    UNION ALL
    SELECT N+1 
    FROM R
    WHERE N < 12
)

SELECT LEFT(DATENAME(MONTH,DATEADD(MONTH,-N,GETDATE())),3) AS [month]
FROM R

上記のスクリプトは完全に機能しますが、私の問題は、それがどのように機能するのか理解できないことです。私はCTEで働いたことはありません。

だから教えて の意味は何ですか WITH R(N) AS

このSQLを見てください

SELECT LEFT(DATENAME(MONTH,DATEADD(MONTH,-N,GETDATE())),3) AS [month] FROM R
when above sql execute how it is getting value for -N ??
because here i have not set anything for -N ??

ですから、全体がどのように機能するかを理解するのを手伝ってください。かく

質問の第 2 段階

ただ見て、教えてください

;WITH months(MonthNumber) AS
(
    SELECT 0
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < 12
)

なぜ下の部分が初めて実行されるのか、私には明らかではありません

SELECT 0
UNION ALL
SELECT MonthNumber+1 
FROM months
WHERE MonthNumber < 12

そして2回目からはこの下の部分だけ実行

SELECT MonthNumber+1 
FROM months
WHERE MonthNumber < 12

Unionを使用して2つのSQLステートメントを記述して実行すると、常に2つのSQL状態からデータが返されますが、特にこの場合は2回目から、この部分のみが実行される理由

SELECT MonthNumber+1 
FROM months
WHERE MonthNumber < 12

基本的に、再帰手法を使用した CTE に慣れていないため、状況が明確になっていません。可能であれば、CTE 再帰がどのように機能するかについて説明してください。

DECLARE @TotaDays SMALLINT
DECLARE @Month VARCHAR(15)
DECLARE @Year SMALLINT
DECLARE @date DATETIME 
SET @Month = 'January'
SET @Year = 2015
SET @date = '01 ' + @Month + ' ' + CONVERT(VARCHAR(4),@Year)
SET @TotaDays = 0
SELECT @TotaDays = DATEDIFF(DAY, @date, DATEADD(MONTH, 1, @date))

;WITH months(MonthNumber) AS
(
    SELECT 1
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < @TotaDays
)

select * from months;
4

8 に答える 8

16

Common Table ExpressionWith R(N)です。MDSN より:

共通テーブル式 (CTE) は、単一の SELECT、INSERT、UPDATE、DELETE、または CREATE VIEW ステートメントの実行範囲内で定義される一時的な結果セットと考えることができます。CTE は、オブジェクトとして格納されず、クエリの間だけ存続するという点で、派生テーブルに似ています。派生テーブルとは異なり、CTE は自己参照することができ、同じクエリで複数回参照できます。

R、生成する結果セット (またはテーブル) の名前です。そして、Nmonth番号です。

特に、この CTE はRecursive Common Table Expressionです。MSDN から:

共通テーブル式 (CTE) には、それ自体を参照できるという大きな利点があり、それによって再帰的な CTE が作成されます。再帰的 CTE は、最初の CTE が繰り返し実行され、完全な結果セットが得られるまでデータのサブセットを返すものです。

CTE を使用する場合、私の提案は名前でより説明的になります。したがって、あなたの例では、次を使用できます。

;WITH months(MonthNumber) AS
(
    SELECT 0
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < 12
)
select *
from months;

私のバージョンでmonthsは、 は生成する結果セットの名前で、monthnumberは値です。これにより、0 ~ 12 の月番号のリストが生成されます (デモを参照)。

結果:

| MONTHNUMBER |
---------------
|           0 |
|           1 |
|           2 |
|           3 |
|           4 |
|           5 |
|           6 |
|           7 |
|           8 |
|           9 |
|          10 |
|          11 |
|          12 |

そのSELECT直後のステートメントは、CTE 結果セットの値を使用して月の名前を取得しています。

最終クエリ (デモを参照):

;WITH months(MonthNumber) AS
(
    SELECT 0
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < 12
)
SELECT LEFT(DATENAME(MONTH,DATEADD(MONTH,-MonthNumber,GETDATE())),3) AS [month]
FROM months;
于 2013-01-04T10:57:36.007 に答える
1

RCTE の名前を(N)定義し、CTE 内の列の名前を定義します。この場合、列は 1 つだけです。

ステートメントの 2 番目の部分で、R から選択していることがわかります。

つまり、CTE定義のアンカー部分の最初で唯一の列であり、後でCTE定義の再帰部分で指定する(N)ときです。select 0select N+1

于 2013-01-04T10:43:44.667 に答える