ভেরিয়েবল হিসাবে কেস স্টেটমেন্টে 100 এরও বেশি এন্ট্রি থাকবে কীভাবে


11

আমি> 100 টি পছন্দ সহ একটি কেস স্টেটমেন্ট লিখেছিলাম যেখানে আমি সাধারণ ক্যোয়ারিতে 4 জায়গায় একই বিবৃতিটি ব্যবহার করছি।

তাদের মধ্যে একটি ইউনিয়নের সাথে একই প্রশ্নটি দু'বার করে তবে একটি গণনাও করছে এবং তাই গোষ্ঠীটির সাথে কেস স্টেটমেন্টও রয়েছে।

এটি এমন কিছু সংস্থার নাম পুনর্বিবেচনা করতে হবে যেখানে একই সংস্থার বিভিন্ন রেকর্ড আলাদাভাবে বানান।

আমি একটি ভেরিয়েবলকে ভারচর (MAX) হিসাবে ঘোষণা করার চেষ্টা করেছি

declare @CaseForAccountConsolidation varchar(max)

SET @CaseForAccountConsolidation = 'CASE 
       WHEN ac.accountName like ''AIR NEW Z%'' THEN ''AIR NEW ZEALAND''
       WHEN ac.accountName LIKE ''AIR BP%'' THEN ''AIR BP''
       WHEN ac.accountName LIKE ''ADDICTION ADVICE%'' THEN ''ADDICTION ADVICE''
       WHEN ac.accountName LIKE ''AIA%'' THEN ''AIA''
       ...

যখন আমি এটি আমার নির্বাচিত বিবৃতিতে ব্যবহার করতে গিয়েছিলাম - ক্যোয়ারী সবেমাত্র কেস স্টেটমেন্টটিকে পাঠ্য হিসাবে ফিরিয়ে দিয়েছে এবং এটি মূল্যায়ন করে নি।

আমি এটি দ্বারা গ্রুপে এটি ব্যবহার করতে অক্ষম ছিলাম - আমি এই ত্রুটি বার্তাটি পেয়েছি:

Each GROUP BY expression must contain at least one column that is not an outer reference.

আদর্শভাবে আমি কেবলমাত্র একটি জায়গায় সিএসইটি রাখতে চাই - যাতে আমার কোনও লাইন আপডেট করার এবং অন্য কোথাও অনুলিপি না করার কোনও সম্ভাবনা না থাকে।

এটি করার কিছু উপায় আছে?

আমি অন্যান্য উপায়ে উন্মুক্ত (সম্ভবত কোনও ফাংশন - তবে এগুলি কীভাবে এটি ব্যবহার করা যায় তা আমি নিশ্চিত নই)

আমি বর্তমানে যে নির্বাচনটি ব্যবহার করছি তার একটি নমুনা এখানে দেওয়া হল

SELECT 
   SUM(c.charge_amount) AS GSTExcl
   ,dl.FirstDateOfMonth AS MonthBilled
   ,dl.FirstDateOfWeek AS WeekBilled
   ,CASE 
       WHEN ac.accountName like 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
       WHEN ac.accountName LIKE 'AIR BP%' THEN 'AIR BP'
       WHEN ac.accountName LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
       WHEN ac.accountName LIKE 'AIA%' THEN 'AIA'
       ELSE ac.accountName
   END AS accountName
   ,dl.FinancialYear
   ,CONVERT(Date,c.date_charged) AS date_charged
FROM [accession] a
   LEFT JOIN account_code ac ON a.account_code_id = ac.account_code_id
   LEFT Join charge c ON a.accession_id = c.accession_id
   LEFT JOIN dateLookup dl ON convert(date,c.date_charged) = dl.date
WHERE a.datecreated = CONVERT(DATE,now())
GROUP BY
   dl.FirstDateOfMonth
   ,dl.FinancialYear
   ,dl.FirstDateOfWeek
   ,CONVERT(Date,c.date_charged)
   ,CASE 
       WHEN ac.accountName like 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
       WHEN ac.accountName LIKE 'AIR BP%' THEN 'AIR BP'
       WHEN ac.accountName LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
       WHEN ac.accountName LIKE 'AIA%' THEN 'AIA'
       ELSE ac.accountName
   END

UNION

SELECT 
   SUM(c.charge_amount) AS GSTExcl
   ,dl.FirstDateOfMonth AS MonthBilled
   ,dl.FirstDateOfWeek AS WeekBilled
   ,CASE 
       WHEN ac.accountName like 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
       WHEN ac.accountName LIKE 'AIR BP%' THEN 'AIR BP'
       WHEN ac.accountName LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
       WHEN ac.accountName LIKE 'AIA%' THEN 'AIA'
       ELSE ac.accountName
   END AS accountName
   ,dl.FinancialYear
   ,CONVERT(Date,c.date_charged) AS date_charged
FROM [accession] a
   LEFT JOIN account_code ac ON a.account_code_id = ac.account_code_id
   LEFT Join charge c ON a.accession_id = c.accession_id
   LEFT JOIN dateLookup dl ON convert(date,c.date_charged) = dl.date
WHERE a.datecreated = DATEADD(YEAR,-1,CONVERT(DATE,now()))
GROUP BY
   dl.FirstDateOfMonth
   ,dl.FinancialYear
   ,dl.FirstDateOfWeek
   ,CONVERT(Date,c.date_charged)
   ,CASE 
       WHEN ac.accountName like 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
       WHEN ac.accountName LIKE 'AIR BP%' THEN 'AIR BP'
       WHEN ac.accountName LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
       WHEN ac.accountName LIKE 'AIA%' THEN 'AIA'
       ELSE ac.accountName
   END

এই ইউনিয়নটির উদ্দেশ্য হ'ল সময়কালের জন্য সমস্ত ডেটা ফেরত দেওয়া এবং 12 মাস আগে একই সময়ের জন্য ডেটা ফিরিয়ে আনা ALSO

সম্পাদনা: একটি অনুপস্থিত "ক্যাচ-সমস্ত"
EDIT2 যুক্ত করেছে: ইউনিয়ন বিবৃতি
EDIT3 এর একটি দ্বিতীয় Added যুক্ত করেছে: কিছু অন্যান্য প্রয়োজনীয় উপাদান অন্তর্ভুক্ত করার জন্য গ্রুপকে সংশোধন করেছে


ইউনিয়ন 2 অংশ পৃথক কিভাবে? তারা কিছুটা পৃথক শর্ত বাদে মোটামুটি একই রকম দেখাচ্ছে similar
ypercubeᵀᴹ

এটিই মূল পার্থক্য। তারিখটিতে দুটি পৃথক শর্ত আজ 12 মাস পূর্বে এবং একই তারিখ দেয়। এর অর্থ আমি তারপরে উপস্থাপনা স্তরটিতে 12 মাস আগে সেই দিনের এবং একই দিনের জন্য সংখ্যাগুলি তুলনা করতে পারি - তবে একক এসকিউএল কোয়েরি চালাচ্ছি।
কিল্টনেন

3
কেন একটি একক নির্বাচন না WHERE a.datecreated = CONVERT(DATE,now()) OR a.datecreated = DATEADD(YEAR,-1,CONVERT(DATE,now()))?
ypercubeᵀᴹ

@ ypercube- এর সহজ উত্তরটি হ'ল প্রথমে এটি তৈরি করার সময় আমি এমনভাবে একটি অনুলিপি করছিলাম যা আমি এটি অন্য কোথাও করেছিলাম যা ইউনিয়ন ব্যবহার করেছিল। কিছুটা আরও জটিল যে তারিখ সীমাবদ্ধতা আসলে আজকের চেয়ে 12 বছরের আগের চেয়ে একই জটিল এবং একই তারিখ। আমি যে তারিখের সীমাটি বেছে নিচ্ছি তা হ'ল 1 জুলাই থেকে বর্তমান তারিখ + 1 জুলাই থেকে তার ঠিক 12 মাস আগের তারিখ পর্যন্ত। (আর্থিক বছর তারিখের ভিএস শেষ অর্থবছর ওয়াইটিডি 12 মাস আগে - এটি বৃদ্ধি বা অন্যথায় আর্থিক বছরের তুলনা করে)। তবে অ্যান্ড্রিএম হিসাবে এবং আপনার পরামর্শ অনুসারে, আমি ইউনিয়ন
বিয়োগের

উত্তর:


11

CASE এক্সপ্রেশনটির পুনরাবৃত্তি দূর করার একটি সহজ উপায় হ'ল ক্রস প্রয়োগ করুন এইভাবে:

SELECT 
   SUM(c.charge_amount) AS GSTExcl
   ,dl.FirstDateOfMonth AS MonthBilled
   ,dl.FirstDateOfWeek AS WeekBilled
   ,x.accountName
   ,dl.FinancialYear
   ,CONVERT(Date,c.date_charged) AS date_charged
FROM [accession] a
   LEFT JOIN account_code ac ON a.account_code_id = ac.account_code_id
   CROSS APPLY
   (
    SELECT 
       CASE 
           WHEN ac.accountName like 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
           WHEN ac.accountName LIKE 'AIR BP%' THEN 'AIR BP'
           WHEN ac.accountName LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
           WHEN ac.accountName LIKE 'AIA%' THEN 'AIA'
       END AS accountName
   ) AS x
   LEFT Join charge c ON a.accession_id = c.accession_id
   LEFT JOIN dateLookup dl ON convert(date,c.date_charged) = dl.date
GROUP BY
   dl.FirstDateOfMonth
   ,x.AccountName

ক্রস প্রয়োগের সহায়তায় আপনি আপনার CASE এক্সপ্রেশনটিতে এমন একটি নাম অর্পণ করুন যাতে এটি আপনার বিবৃতিতে যে কোনও জায়গায় উল্লেখ করা যেতে পারে। এটি কাজ করে কারণ কঠোরভাবে বলতে গেলে আপনি নেস্টেড নির্বাচন করে গণিত কলামটি সংজ্ঞায়িত করছেন - ক্রস প্রয়োগের অনুসরণ করে FROM- কম SELECT।

এটি কোনও উত্পন্ন টেবিলের অ্যালিজেড কলাম উল্লেখ করার মতোই - যা প্রযুক্তিগতভাবে এই নেস্টেড নির্বাচন করুন। এটি উভয় একটি সম্পর্কিত সম্পর্কযুক্ত subquery এবং একটি উত্পন্ন টেবিল। একটি সম্পর্কযুক্ত সাবকোয়ারি হিসাবে, এটি বাহ্যিক স্কোপের কলামগুলিকে রেফারেন্স করার অনুমতি দেয় এবং একটি উত্পন্ন টেবিল হিসাবে এটি বাহ্যিক সুযোগটিকে এটি সংজ্ঞায়িত কলামগুলিকে রেফারেন্স করতে দেয়।

একই CASE এক্সপ্রেশন ব্যবহার করে এমন একটি ইউনিয়ন ক্যোয়ারীর জন্য আপনাকে প্রতিটি পায়ে এটি সংজ্ঞায়িত করতে হবে, CASE এর পরিবর্তে সম্পূর্ণ ভিন্ন প্রতিস্থাপন পদ্ধতিটি ব্যবহার করা ছাড়া এটির পক্ষে কোনও কার্যকারিতা নেই। যাইহোক, আপনার নির্দিষ্ট ক্ষেত্রে ইউনিয়ন ছাড়া ফলাফল আনা সম্ভব।

দুটি পা শুধুমাত্র WHERE অবস্থায় পৃথক। একটি এটি আছে:

WHERE a.datecreated = CONVERT(DATE,now())

এবং অন্যান্য এটি:

WHERE a.datecreated = DATEADD(YEAR,-1,CONVERT(DATE,now()))

আপনি তাদের এইভাবে একত্রিত করতে পারেন:

WHERE a.datecreated IN (
                        CONVERT(DATE,now()),
                        DATEADD(YEAR,-1,CONVERT(DATE,now()))
                       )

এবং এই উত্তরের শুরুতে পরিবর্তিত SELECT এ এটি প্রয়োগ করুন।


অ্যান্ড্রি - খুব ভাল! আপনার দ্বারা অনুপ্রাণিত হয়ে :-), আমি আমার উত্তরের সাথে আরও একটি পদ্ধতির যোগ করেছি - ক CTE- আমি নিশ্চিত নই যে কোনটি সেরা পন্থা!
ভ্যারেস

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

@ কিল্টেনেন ড্রপ করুন UNIONএবং কেবলমাত্র datecreatedআপনার GROUP BYঅনুচ্ছেদে কলামটি অন্তর্ভুক্ত করুন (এবং WHEREআপনার আগ্রহী উভয় তারিখ অন্তর্ভুক্ত করার জন্য ধারাটি আপডেট করুন )।
স্কট এম

@ স্কটএম: আমি মনে করি না যে ওপিকে গ্রোপ datecreatedবাই দ্বারা কলামটি অন্তর্ভুক্ত করা দরকার । তা ছাড়া, আমি সম্পূর্ণরূপে একমত, তারা কেবল যেখানে ক্লউগুলি একত্রিত করতে পারে এবং ইউনিয়নটিকে খাঁজতে পারে।
অ্যান্ড্রি এম

@ স্কট-এম আমাকে আগামীকাল এই চেষ্টা করতে হবে তবে আমার সন্দেহ হয় যে এতটা ভাল কাজ করে না। এটি আসলে একদিন নয় - এটি সম্ভাব্য কয়েক মাস। আমার মনে হয় আমি যা চালিয়েছি তার মধ্যে দৈনিক ডেটা 11 মাস পর্যন্ত ছিল - সুতরাং যেখানে শুরু হয়েছিল এবং শেষ হয়েছিল এবং তারপরে আমাকে 12 মাস আগে একই সময়ের জন্য একটি ওআর চালাতে হয়েছিল। আমি মনে করি এটি একটি পারফরম্যান্স হিট দিয়ে শেষ হয়েছে। আমাকে আবার চেষ্টা করতে হবে - তবে আমি মনে করি যে ইউনিয়ন চালানোর সময় আমার যে সমস্যা ছিল না সেগুলির মধ্যে পড়েছিলাম। অবশ্যই এটি নিজস্ব সমস্যা নিয়ে আসে। আমি বর্তমানে যার সাথে কুস্তি করছি তার মতো ..
কিল্টনেন

22

তথ্য একটি টেবিলের মধ্যে রাখুন

CREATE TABLE AccountTranslate (wrong VARCHAR(50), translated(VARCHAR(50));

INSERT INTO AccountTranslate VALUES ('ADDICTION ADVICE%','ADDICTION ADVICE');
INSERT INTO AccountTranslate VALUES ('AIR BP%','AIR BP');
INSERT INTO AccountTranslate VALUES ('AIR NEW Z%', 'AIR NEW ZEALAND');

এবং এতে যোগ দিন।

SELECT ...,COALESCE(AccountTranslate.translated, ac.accountName) AS accountName
FROM
...., 
account_code ac left outer join 
AccountTranslate at on ac.accountName LIKE AccountTranslate.wrong

এইভাবে আপনি একাধিক জায়গায় ডেটা আপ টু ডেট এড়াতে পারবেন। আপনার COALESCEযেখানে প্রয়োজন সেখানে কেবল ব্যবহার করুন । VIEWঅন্যান্য পরামর্শ অনুসারে আপনি এটি সিটিই বা এসগুলিতে অন্তর্ভুক্ত করতে পারেন ।


4

আমি মনে করি অন্য বিকল্পটি যদি আপনার এটির বেশ কয়েকটি জায়গায় পুনরায় ব্যবহার করার প্রয়োজন হয় তবে একটি ইনলাইন টেবিলের মূল্যবান ফাংশনটি ভাল হবে।

CREATE FUNCTION dbo.itvf_CaseForAccountConsolidation
    ( @au_lname VARCHAR(8000) ) 
RETURNS TABLE 
RETURN 
SELECT  
  CASE
    WHEN UPPER(@au_lname) LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
    WHEN UPPER(@au_lname) LIKE 'AIR BP%'  THEN 'AIR BP'
    WHEN UPPER(@au_lname) LIKE 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
    ELSE '****ERROR****'  -- you may or may not need this! 
                         -- If converting every record, then yes, if not, then no!
                         -- Errors should stand out on browsing and it's easy to search for!
  END AS wrong

--Copied from verace

আপনার নির্বাচন এই মত হবে।

  SELECT 
   SUM(c.charge_amount) AS GSTExcl
   ,dl.FirstDateOfMonth AS MonthBilled
   ,dl.FirstDateOfWeek AS WeekBilled
   ,dd.wrong AS accountName
   ,dl.FinancialYear
   ,CONVERT(Date,c.date_charged) AS date_charged
FROM [accession] a
   LEFT JOIN account_code ac ON a.account_code_id = ac.account_code_id
   LEFT Join charge c ON a.accession_id = c.accession_id
   LEFT JOIN dateLookup dl ON convert(date,c.date_charged) = dl.date
   CROSS APPLY  dbo.itvf_CaseForAccountConsolidation( ac.accountName)dd
GROUP BY
   dl.FirstDateOfMonth 
   ,dl.FirstDateOfWeek 
   ,wrong 
   ,dl.FinancialYear
   ,CONVERT(Date,c.date_charged)

এছাড়াও, আমি এটি পরীক্ষা করিনি এবং কোডটির কার্য সম্পাদনও নির্ধারণ করা উচিত।

সম্পাদনা 1 : আমি মনে করি অ্যান্ডরি ইতিমধ্যে এমন একটি দিয়েছে যা ক্রস প্রয়োগ ব্যবহার করে যা কোডটিকে পুনরায় যোগাযোগ করে। ঠিক আছে, এইটিকে কেন্দ্রিয় করা যেতে পারে যেহেতু আপনি কোডের অন্যান্য অংশে একই পুনরাবৃত্তি করছেন তাই ফাংশনটিতে যে কোনও পরিবর্তন ঘটবে তা সবার মধ্যেই প্রতিফলিত হবে।


3

VIEWআপনি যা করতে চেষ্টা করছেন তা করার জন্য আমি একটি ব্যবহার করব। আপনি অবশ্যই অন্তর্নিহিত তথ্য সংশোধন করতে পারেন, তবে প্রায়শই এই সাইটে যারা প্রশ্ন জিজ্ঞাসা করছেন তাদের (পরামর্শদাতারা / ডিবিএস /) এটি করার ক্ষমতা রাখেন না। একটি ব্যবহার করে VIEWএই সমস্যার সমাধান করতে পারে! আমি এই UPPERফাংশনটি ব্যবহার করেছিলাম - এরকম ক্ষেত্রে ত্রুটিগুলি সমাধান করার একটি সস্তা উপায়।

এখন, আপনি কেবল VIEWএকবার ঘোষণা করুন এবং এটি যে কোনও জায়গায় ব্যবহার করতে পারেন! এইভাবে, আপনার কেবলমাত্র একটি জায়গা রয়েছে যেখানে আপনার ডেটা রূপান্তর অ্যালগরিদম সংরক্ষণ এবং চালিত হয়, যার ফলে আপনার সিস্টেমের নির্ভরযোগ্যতা এবং দৃust়তা বৃদ্ধি পায়।

আপনি একটি সিটিই ( সাধারণ টেবিল এক্সপ্রেশন ) ও ব্যবহার করতে পারেন - উত্তরের নীচে দেখুন!

আপনার প্রশ্নের উত্তর দেওয়ার জন্য, আমি নিম্নলিখিতগুলি করেছি:

একটি নমুনা সারণী তৈরি করুন:

CREATE TABLE my_error (wrong VARCHAR(50));

কয়েকটি নমুনা রেকর্ড সন্নিবেশ করান:

INSERT INTO my_error VALUES ('Addiction Advice Services Ltd.');
INSERT INTO my_error VALUES ('AIR BP_and-mistake');
INSERT INTO my_error VALUES ('AIR New Zealand Airlines');

তারপরে VIEWপ্রস্তাবিত হিসাবে একটি তৈরি করুন :

CREATE VIEW my_error_view AS 
SELECT 
  CASE
    WHEN UPPER(wrong) LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
    WHEN UPPER(wrong) LIKE 'AIR BP%'  THEN 'AIR BP'
    WHEN UPPER(wrong) LIKE 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
    ELSE '***ERROR****' -- You may or may not need this.
                        -- It's attention grabbing (report) and easy to search for (SQL)!
  END AS wrong
FROM my_error;

তারপরে, SELECT আপনার থেকে VIEW:

SELECT * FROM my_error_view
ORDER BY wrong;

ফলাফল:

ADDICTION ADVICE
AIR BP
AIR NEW ZEALAND

এট ভয়েইল!

আপনি এখানে সব কিছু ঝাঁকুনিতে খুঁজে পেতে পারেন ।

CTEদৃষ্টীকোণ:

উপরের মত একই, বাদে নিম্নলিখিত হিসাবে CTEপ্রতিস্থাপিত VIEWহয়:

WITH my_cte AS
(
  SELECT 
  CASE
    WHEN UPPER(wrong) LIKE 'ADDICTION ADVICE%' THEN 'ADDICTION ADVICE'
    WHEN UPPER(wrong) LIKE 'AIR BP%'  THEN 'AIR BP'
    WHEN UPPER(wrong) LIKE 'AIR NEW Z%' THEN 'AIR NEW ZEALAND'
    ELSE '****ERROR****'  -- you may or may not need this! 
                         -- If converting every record, then yes, if not, then no!
                         -- Errors should stand out on browsing and it's easy to search for!
  END AS wrong
  FROM my_error
)
SELECT * FROM my_cte;

ফলাফল একই. তারপরে CTEআপনি অন্য যে কোনও টেবিলের মতো সেইরকম আচরণ করতে পারবেন - SELECTকেবলমাত্র এর জন্য ! ফিডল এখানে পাওয়া যায়

সামগ্রিকভাবে, আমি মনে করি যে VIEWএই ক্ষেত্রে পদ্ধতির আরও ভাল!


0

এমবেডেড টেবিল

select id, tag, trans.val 
  from [consecutive] c
  join ( values ('AIR NEW Z%', 'AIR NEW ZEALAND'),
                ('AIR BP%',    'AIR BP')
       ) trans (lk, val)
    on c.description like trans.lk 

ইউনিয়নটি এড়িয়ে যান এবং ORঅন্যদের পরামর্শ অনুসারে একটি ব্যবহার করুন ।

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