WHERE ধারাটিতে রেফারেন্স ওরফে (SELECT এ গণনা করা)


130
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE BalanceDue > 0 --error

নির্বাচিত কলামগুলির তালিকায় ভেরিয়েবল হিসাবে সেট করা গণনা করা মান 'ব্যালেন্সডিউ' WHERE ধারাটিতে ব্যবহার করা যাবে না।

এটা কি উপায় আছে? এই সম্পর্কিত প্রশ্নে ( মাইএসকিউএল সিলেক্ট স্ট্যাটমেন্ট ইন ভেরিয়েল ক্লাউজ-এ একটি ভেরিয়েবল ব্যবহার করে ) মনে হচ্ছে উত্তরটি উত্তরটির মতো মনে হবে, আসলে, না, আপনি কেবল হিসাবটি লিখবেন ( এবং ক্যোয়ারিতে সেই গণনাটি সম্পাদন করবেন), কোনওটিই নয় যা সন্তোষজনক।

উত্তর:


237

অর্ডার বাই ব্যতীত আপনি একটি উপন্যাসটি রেফারেন্স করতে পারবেন না কারণ নির্বাচন দ্বিতীয় শ্রেণীর যেটি মূল্যায়ন করা হয় তা বেছে নিন। দুটি কর্মক্ষেত্র:

SELECT BalanceDue FROM (
  SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
  FROM Invoices
) AS x
WHERE BalanceDue > 0;

বা কেবল প্রকাশটি পুনরাবৃত্তি করুন:

SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE  (InvoiceTotal - PaymentTotal - CreditTotal)  > 0;

আমি উত্তরোত্তর পছন্দ। যদি অভিব্যক্তিটি অত্যন্ত জটিল (বা গণনা করার জন্য ব্যয়বহুল) হয় তবে আপনার পরিবর্তে সম্ভবত একটি গণিত কলামটি বিবেচনা করা উচিত (এবং সম্ভবত অবিরত থাকবে), বিশেষত যদি অনেকগুলি প্রশ্ন এই একই অভিব্যক্তির উল্লেখ করে।

পিএস আপনার ভয় ভিত্তিহীন বলে মনে হচ্ছে। অন্তত এই সাধারণ উদাহরণে, এসকিউএল সার্ভার কেবল একবার গণনা সম্পাদন করার জন্য যথেষ্ট স্মার্ট, যদিও আপনি এটি দুবার উল্লেখ করেছেন। এগিয়ে যান এবং পরিকল্পনা তুলনা; আপনি দেখতে পাবেন তারা অভিন্ন। আপনার যদি আরও জটিল কেস হয় যেখানে আপনি একাধিকবার ভাব প্রকাশের মূল্যায়ন দেখতে পান তবে দয়া করে আরও জটিল প্রশ্ন এবং পরিকল্পনা পোস্ট করুন।

এখানে 5 টি উদাহরণস্বরূপ ক্যোয়ারী রয়েছে যা সমস্ত একই কার্যকর প্রয়োগের পরিকল্পনা করে:

SELECT LEN(name) + column_id AS x
FROM sys.all_columns
WHERE LEN(name) + column_id > 30;

SELECT x FROM (
SELECT LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE x > 30;

SELECT LEN(name) + column_id AS x
FROM sys.all_columns
WHERE column_id + LEN(name) > 30;

SELECT name, column_id, x FROM (
SELECT name, column_id, LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE x > 30;

SELECT name, column_id, x FROM (
SELECT name, column_id, LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE LEN(name) + column_id > 30;

পাঁচটি প্রশ্নের জন্য ফলাফল তৈরির ফলাফল:

এখানে চিত্র বর্ণনা লিখুন


11
কি দারুন. এসকিউএল সার্ভার কেবল একবার গণনা সম্পাদনের জন্য যথেষ্ট স্মার্ট
বিকল্প

5
বাহ এটা খুব উচ্চ মানের উত্তর!
সিদ্ধার্থ

মার্জ স্টেটমেন্টে আমার কিছু অতিরিক্ত শর্তযুক্ত দরকার ছিল এবং এটি কেবলমাত্র এটিই কাজটি করতে পেরেছিলাম। ধন্যবাদ!
এরিক বার্ডো

1
@ এরিকবার্ডো আপনি যদি ব্যবহার করছেন MERGEতবে দয়া করে নিশ্চিত হয়ে নিন যে আপনি এই সমস্তটি বিবেচনায় নিয়েছেন: MERGEসাবধানতার সাথে
অ্যারন বার্ট্র্যান্ড

11

আপনি এটি ব্যবহার করে করতে পারেন cross apply

SELECT c.BalanceDue AS BalanceDue
FROM Invoices
cross apply (select (InvoiceTotal - PaymentTotal - CreditTotal) as BalanceDue) as c
WHERE  c.BalanceDue  > 0;

4

বাস্তবে কার্যকরভাবে একটি পরিবর্তনশীল সংজ্ঞায়িত করা সম্ভব যা নির্বাচন, যেখানে এবং অন্যান্য ধারা উভয় ক্ষেত্রে ব্যবহার করা যেতে পারে।

একটি ক্রস জয়েন অবশ্যই রেফারেন্সযুক্ত টেবিল কলামগুলিতে যথাযথ বাধ্যবাধকতার জন্য মঞ্জুরি দেয় না, তবে আউটার প্রয়োগ করে - এবং নালকে আরও স্বচ্ছভাবে আচরণ করে।

SELECT
    vars.BalanceDue
FROM
    Entity e
OUTER APPLY (
    SELECT
        -- variables   
        BalanceDue = e.EntityTypeId,
        Variable2 = ...some..long..complex..expression..etc...
    ) vars
WHERE
    vars.BalanceDue > 0

সৈয়দ মেহরোজ আলমের কাছে কুডোস

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.