كيفية إعادة استخدام الأعمدة الحيوية في Oracle SQL البيان ؟

StackOverflow https://stackoverflow.com/questions/743772

  •  09-09-2019
  •  | 
  •  

سؤال

أحاول إعادة استخدام بعض الأعمدة التي يمكنني حساب حيوي في Oracle SQL ، شيء من هذا القبيل

SELECT
    A*2 AS P,
    P+5 AS Q
FROM tablename

حيث 'tablename' عمود يسمى 'A', ولكن لا الأخرى وcolums.هذا يعطيني

ORA-00904: "P": invalid identifier

أنا أعرف كيفية العمل حول هذا باستخدام فرعي مثل

SELECT P, P+5 AS Q
FROM ( SELECT A*2 AS P FROM tablename )

ولكن أعتقد أن هذا هو قبيح نوعا ما.وعلاوة على ذلك أنا تريد أن تجعل من الاستعلام إلى حد ما أكثر تعقيدا ، مثلإعادة استخدام 'Q' كذلك, و أنا لا أريد أن خلق آخر فرعي.

تحديث:السبب أريد أن متجر حساب 'P' أن كنت تريد أن تجعل الأمر أكثر تعقيدا ، وإعادة استخدام 'P' عدة مرات.لذلك أنا لا أريد أن أقول بكل صراحة 'A*2+5 س' ، لأن من شأنها أن تصبح بسرعة إلى مرهقة كما 'P' يحصل أكثر تعقيدا.

يجب أن يكون هناك وسيلة جيدة للقيام بذلك ، أي أفكار ؟

تحديث:أود أن أشير إلى أنني لست DB-المشرف :(.


تحديث:العالم الحقيقي سبيل المثال, مع المزيد من الخرسانة الاستعلام.ما أود القيام به هو:

SELECT 
    SL/SQRT(AB) AS ALPHA,
    5*LOG(10,ALPHA) AS B,
    2.5*LOG(10,1-EXP(-5/ALPHA)*(5/ALPHA+1)) AS D
    BS -2.74 + B + D AS BSA
FROM tablename

الآن, لقد كتبت ذلك الذي يعمل لكن هو قبيح:

SELECT
    SL/SQRT(AB) AS ALPHA,
    5*LOG(10,SL/SQRT(AB)) AS B,
    2.5*LOG(10,1-EXP(-5/(SL/SQRT(AB)))*(5/(SL/SQRT(AB))+1)) AS D
    BS -2.74 + 5*LOG(10,SL/SQRT(AB)) + 2.5*LOG(10,1-EXP(-5/(SL/SQRT(AB)))*((5/(SL/SQRT(AB)))+1)) AS BSA
FROM tablename

أنا يمكن أن تفعل كل هذا بعد تلقي البيانات ، ولكن فكرت دعونا نرى كم كنت يمكن أن تسمح قاعدة البيانات به.أيضا أود أن حدد على BSA' وكذلك (الذي يمكنني القيام به الآن مع هذا الاستعلام فرعي/مع-شرط).


تحديث:حسنا, أعتقد الآن أنني انتهيت من كيد رو' و ديف كوستا الحل.وإن كان باكس' و ينس Schauder الحل من شأنه أن تبدو أفضل ، ولكن لا أستطيع استخدامها منذ أنا لا ديسيبل.الآن أنا لا أعرف من علامة أفضل إجابة :).

WITH 
  A1 AS ( 
    SELECT A0.*, 
    SL/SQRT(AB) AS ALPHA
    FROM tablename A0
  ),
  A2 AS (
    SELECT A1.*, 
    5*LOG(10,ALPHA) AS B,
    2.5*LOG(10,1-EXP(-5/ALPHA)*((5/ALPHA)+1)) AS D
    FROM A1
  )
SELECT
  ALPHA, B, D, BS,
  BS -2.74 + B + D AS BSA
FROM A2

BTW, في حالة أي شخص مهتم ، SB هو 'سطوع السطح من المجرات ، B و D هي تصحيح الشروط.

هل كانت مفيدة؟

المحلول

لدينا هذه المشكلة نفسها في SQL Server (إنها مشكلة ANSI). أعتقد أنه يهدف إلى تجنب تأثيرات التعرج المربكة:

SELECT A * 2 AS A
    ,A * 3 AS B -- This is the original A, not the new A
FROM whatever

نحن نعمل حولها عن طريق تكديس تعبيرات الجدول المشتركة:

WITH A1 AS (
    SELECT A * 2 AS A
    FROM whatever
)
,A2 AS (
    SELECT A1.*
        ,A * 3 AS B
    FROM A1
)
,A3 AS (
    SELECT A2.*
        ,A + B AS X
    FROM A2
)
SELECT *
FROM A3

هذا هو الإصدار الأكثر قراءة وصيانة ومتابعة.

للحصول على التحديثات، يوجد حل مبدئي محتمل SQL Server باستخدام العمود = Name = Notation، حيث يمكنك الرجوع إلى عمود تم تحديثه مسبقا في القائمة. ولكن لا يمكن استخدام هذا في الاختيار.

آمل أن تتم إضافة بعض القدرة على تكديس التعبيرات (بدون استخدام A Scalar UDF) إلى ANSI SQL في مرحلة ما في المستقبل.

نصائح أخرى

لست متأكدا من أنك تستطيع القيام بذلك (لم أرها أبدا) ولكن يمكنك العمل من حولها:

SELECT
    A*2   AS P,
    A*2+5 AS Q
FROM tablename

هذا أفضل بالتأكيد من تقديم فرعي.

الطريقة الأخرى الوحيدة التي أقترحها هي إنشاء طريقة عرض تعطيك أعمدة P / Q Type (باستخدام الصيغ أعلاه) والتي من شأنها تبسيط نص الاستعلام على الأقل. ثم يمكنك فقط:

SELECT P, Q FROM viewintotablename

لا توجد طريقة مباشرة للقيام بذلك في SQL.

ولكن يمكنك تحديد وظيفة باستخدام PL / SQL. لذلك سوف حدد الخاص بك تبدو مثل هذا

select 
    P(A), 
    Q(P(A)) 
from tablename

بالنسبة إلى P و Q هذا ليس (كثيرا) بشكل أفضل ثم الأصل، ولكن إذا كانت الوظائف معقدة، ولا تضطر إلى العديد من المعلمات، فقد تجعل بيانك أكثر قابلية للقراءة.

كما سيتيح لك اختبارك يعمل بشكل مستقل عن عبارة SQL وأي بيانات.

قد ترغب في هذا أفضل قليلا من مثال العرض المضمن الذي قدمته:

WITH inner_view AS ( SELECT A*2 AS P FROM tablename )
SELECT P, P+5 AS Q
FROM inner_view

يرقى إلى نفس الشيء ولكنها أكثر وضوحا قليلا القراءة، كما أعتقد.

إذا كان العمود المحسوب هو شيء سوف تستخدمه في أعمدة متعددة، فقد يكون من المنطقي إنشاء طريقة عرض دائمة.

لدى Oracle 11 (التي لم أستخدمها بعد) ميزة عمود افتراضية قد تكون مفيدة لك.

لا يمكنك ذلك.

إذا كنت لا تريد إعادة تقييم الاسمية المستقية، أضف أ NO_MERGE تلميح للسباق:

سيتم إعادة تقييم هذه الاسمية الاسمية الاسمية في حلقة متداخلة (MERGE يستخدم تلميح):

SELECT  /*+ LEADING(g) USE_NL(g, r) MERGE(g) */
        *
FROM    (
        SELECT  1
        FROM    dual
        UNION ALL
        SELECT  2
        FROM    dual
        ) r, 
        (
        SELECT  SYS_GUID() AS guid
        FROM    dual d
        ) g

---
33CA48C1AB6B4403808FB0219302CE43
711BB04F9AFC406ABAEF8A8F4CFA1266

لن يتم إعادة تقييم هذه الاسمية الاسمية الاسمية في حلقة متداخلة (NO_MERGE يستخدم تلميح):

SELECT  /*+ LEADING(g) USE_NL(g, r) NO_MERGE(g) */
        *
FROM    (
        SELECT  1
        FROM    dual
        UNION ALL
        SELECT  2
        FROM    dual
        ) r, 
        (
        SELECT  SYS_GUID() AS guid
        FROM    dual d
        ) g

------
7715C69698A243C0B379E68ABB55C088
7715C69698A243C0B379E68ABB55C088

في قضيتك، فقط اكتب:

SELECT  BS - 2.74 + d
FROM    (
        SELECT  t2.*, 2.5 * LOG(10, 1 - EXP(-5 / b)) * ((5 / A) + 1) AS d
        FROM    (
                SELECT  t1.*, 5 * LOG(10, alpha) AS b
                FROM    (
                        SELECT  /*+ NO_MERGE */ t.*,
                                SL/SQRT(AB) AS alpha
                        FROM    tablename t
                        ) t1
                ) t2
        ) t3

, ، وهو أكثر كفاءة (EXP و LOG مكلفة) وهي أسهل بكثير تصحيح.

الاسم المستعار إعادة استخدام شائع في مقاومه ومع ذلك يمكن أن يكون الخلط في بعض الأحيان أساسا عند المستعار اسم العمود مع الاسم الموجود داخل الجدول/الاستعلام الفرعي ومحاولة إعادة استخدامها قاعدة البيانات سوف تستخدم العمود الأصلي و لا تستطيع مستعارة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top