একটি এসকিউএল কোয়েরি সহ একাধিক গণনা কীভাবে পাবেন?


315

আমি এই ক্যোয়ারীটি কীভাবে লিখব তা ভাবছি।

আমি জানি যে প্রকৃত বাক্য গঠনটি বোগাস, তবে এটি আপনাকে কী চাই তা বুঝতে সহায়তা করবে। আমার এই ফর্ম্যাটটিতে এটি প্রয়োজন, কারণ এটি অনেক বড় প্রশ্নের সাথে অংশীদার।

SELECT distributor_id, 
COUNT(*) AS TOTAL, 
COUNT(*) WHERE level = 'exec', 
COUNT(*) WHERE level = 'personal'

আমার এগুলি সবই একটি ক্যোয়ারিতে ফিরে আসা দরকার।

এছাড়াও, এটি এক সারিতে থাকা দরকার, সুতরাং নিম্নলিখিতগুলি কাজ করবে না:

'SELECT distributor_id, COUNT(*)
GROUP BY distributor_id'

1
আপনার এই প্রশ্নটি কি সঠিকভাবে কাজ করেছে ?? SELECT distributor_id, COUNT(*) AS TOTAL, COUNT(*) WHERE level = 'exec', COUNT(*) WHERE level = 'personal'
প্রতীক

উত্তর:


689

আপনি CASEএকটি সামগ্রিক ফাংশন সহ একটি বিবৃতি ব্যবহার করতে পারেন । এটি মূলত PIVOTকিছু আরডিবিএমএসের ফাংশন হিসাবে একই জিনিস :

SELECT distributor_id,
    count(*) AS total,
    sum(case when level = 'exec' then 1 else 0 end) AS ExecCount,
    sum(case when level = 'personal' then 1 else 0 end) AS PersonalCount
FROM yourtable
GROUP BY distributor_id

55
চমত্কার, এটি আশ্চর্যজনক। দুর্দান্ত উত্তর। এখানে হোঁচট খাওয়া লোকদের কাছে কেবল একটি নোট note গণনাটি সমস্ত সারি গণনা করবে, কেস স্টেটমেন্টের সাথে যোগ করার সময় যোগফল গণনা হিসাবে একই কাজ করবে।
জন বলিঞ্জার

1
উজ্জ্বল সমাধান! সম্ভবত এটি লক্ষণীয় যে এই পদ্ধতিটি ঠিক তত ভালভাবে কাজ করে যদি আপনি একটি ক্যোয়ারীতে প্রচুর টেবিল একত্রিত করে থাকেন, কারণ সাব-কোয়েরিগুলি ব্যবহার করে সেই পরিস্থিতিতে যথেষ্ট অগোছালো হতে পারে।
ড্যারেন ক্র্যাব

7
এই খুব মার্জিত সমাধানের জন্য ধন্যবাদ। বিটিডব্লিউ, এটি টিএসকিউএল এর সাথেও কাজ করে।
অ্যানি লাগাং

6
কেন এটি সর্বোত্তম উত্তর হতে পারে না: সর্বদা একটি পূর্ণ টেবিল স্ক্যান। একটি নির্বাচনের মধ্যে গণনা-সাবকিউরিয়ান্স বা নেস্টেড গণনাগুলির একটি যোগদান বিবেচনা করুন। তবে কোনও সূচক উপস্থিত না থাকায় এটি সেরা হতে পারে কারণ আপনি কেবল একাধিক টেবিল স্ক্যানের গ্যারান্টি দিয়েছেন।
@

1
@ জনবালিংগার, 'গণনাটি সমস্ত সারি COUNTগণনা করবে ' - distributor_idবুদ্ধিমান গণনা করা হবে । টেবিলের সমস্ত সারি না, তাই না?
ইসতিয়াক আহমেদ

87

একটি উপায় যা নিশ্চিতভাবে কাজ করে

SELECT a.distributor_id,
    (SELECT COUNT(*) FROM myTable WHERE level='personal' and distributor_id = a.distributor_id) as PersonalCount,
    (SELECT COUNT(*) FROM myTable WHERE level='exec' and distributor_id = a.distributor_id) as ExecCount,
    (SELECT COUNT(*) FROM myTable WHERE distributor_id = a.distributor_id) as TotalCount
FROM (SELECT DISTINCT distributor_id FROM myTable) a ;

সম্পাদনা:
আপনি সম্ভবত এই পদ্ধতিটি কেন ব্যবহার করতে চান না এবং এর পরিবর্তে @ টারিনের উত্তরটি বেছে নেওয়া উচিত তার জন্য @ কেভিনবালমফোর্থের পারফরম্যান্স ভেঙে দেখুন। আমি এটি ছেড়ে চলে যাচ্ছি যাতে লোকেরা তাদের বিকল্পগুলি বুঝতে পারে।


2
এটি আমাকে একাধিক গণনা করতে এবং প্রতিটি গণনা কলাম হিসাবে একক নির্বাচনী বিবৃতিতে আউটপুট কী তা সমাধান করতে সহায়তা করেছে। দুর্দান্ত কাজ করে - ধন্যবাদ!
চিহ্নিত করুন

2
আপনি এখানে যা সরবরাহ করেছেন তা আমার একটি প্রকল্পে আমি ব্যবহার করতে সক্ষম হয়েছি। একাধিক প্রশ্নের পরিবর্তে এখন সমস্ত কিছুই একক কোয়েরিতে রয়েছে। পৃষ্ঠাটি একাধিক ক্যোয়ারীর সাথে 5-8 সেকেন্ডের তুলনায় এক সেকেন্ডেরও কম সময়ে লোড হয়। এটা ভাল। ধন্যবাদ, নোটম
ওয়েইন ব্যারন

1
প্রতিটি উপ-ক্যোয়ারী যদি একটি সূচককে হিট করে তবে এটি ভালভাবে কাজ করতে পারে। যদি তা না হয় তবে sum(case...)সমাধানটি বিবেচনা করা উচিত।
YoYo

1
নোট করুন যে স্বতন্ত্র বিকল্প হিসাবে, আমি যেমন সংশোধন করেছি, আপনি / মিহাই শো হিসাবে group byএকটি সম্পূর্ণ নেস্টেড ক্যোয়ারী প্রতিস্থাপনের সুবিধা দিয়ে / আরও ভাল ব্যবহার করতে পারেন count(*)- আরও মাইএসকিউএল কেবল সিনট্যাক্স সরলকরণের সাথে।
YoYo

এই ভাবে JOINS এর চেয়ে আরও ভাল কাজ করে, ধন্যবাদ।
10

43
SELECT 
    distributor_id, 
    COUNT(*) AS TOTAL, 
    COUNT(IF(level='exec',1,null)),
    COUNT(IF(level='personal',1,null))
FROM sometable;

COUNTকেবলমাত্র non nullমানগুলি গণনা করা হয় এবং যদি আপনার শর্তটি সন্তুষ্ট DECODEহয় 1তবেই নাল নালিকাগুলি প্রদান করবে।


যা distributor_idকোয়েরি দেখাবে? এটি মোট 1 টি সারি দেখায়।
ইসতিয়াক আহমেদ

ওপিটির কলামটিতে একটি গ্রুপ রয়েছে যা আমার উত্তরে বাদ দেওয়া হয়েছিল।
মাজিদ লইসি

আপনি আমার জীবন বাঁচিয়েছেন, অন্য সমস্ত প্রশ্নকর্তা মাইএসকিউএলে একাধিক সারি ফিরিয়ে দেন। আপনাকে অনেক ধন্যবাদ
আব্নার

1
@ 8 বছর পরে এটি এখনও সহায়তা করে জানায় আনন্দিত :)
মজিদ লইসি

@ মাজিদলাইসি হ্যাঁ এটি করেছে, আমার ক্যোয়ারির সময়টি এক মিনিট থেকে এক সেকেন্ডের চেয়ে কম পরিবর্তন করেছে। :)
আব্নার

25

অন্যান্য পোস্ট করা উত্তরের উপর বিল্ডিং।

এই দুটিই সঠিক মান তৈরি করবে:

select distributor_id,
    count(*) total,
    sum(case when level = 'exec' then 1 else 0 end) ExecCount,
    sum(case when level = 'personal' then 1 else 0 end) PersonalCount
from yourtable
group by distributor_id

SELECT a.distributor_id,
          (SELECT COUNT(*) FROM myTable WHERE level='personal' and distributor_id = a.distributor_id) as PersonalCount,
          (SELECT COUNT(*) FROM myTable WHERE level='exec' and distributor_id = a.distributor_id) as ExecCount,
          (SELECT COUNT(*) FROM myTable WHERE distributor_id = a.distributor_id) as TotalCount
       FROM myTable a ; 

তবে, কর্মক্ষমতাটি একেবারেই আলাদা, যা ডেটার পরিমাণ বাড়ার সাথে স্পষ্টতই আরও প্রাসঙ্গিক হবে।

আমি দেখতে পেলাম যে, টেবিলে কোনও সূচী সংজ্ঞায়িত করা হয়নি, এসইউএমএস ব্যবহার করে কোয়েরিটি একটি একক টেবিল স্ক্যান করবে while

উদাহরণ হিসাবে, নিম্নলিখিত স্ক্রিপ্টটি চালান:

IF OBJECT_ID (N't1', N'U') IS NOT NULL 
drop table t1

create table t1 (f1 int)


    insert into t1 values (1) 
    insert into t1 values (1) 
    insert into t1 values (2)
    insert into t1 values (2)
    insert into t1 values (2)
    insert into t1 values (3)
    insert into t1 values (3)
    insert into t1 values (3)
    insert into t1 values (3)
    insert into t1 values (4)
    insert into t1 values (4)
    insert into t1 values (4)
    insert into t1 values (4)
    insert into t1 values (4)


SELECT SUM(CASE WHEN f1 = 1 THEN 1 else 0 end),
SUM(CASE WHEN f1 = 2 THEN 1 else 0 end),
SUM(CASE WHEN f1 = 3 THEN 1 else 0 end),
SUM(CASE WHEN f1 = 4 THEN 1 else 0 end)
from t1

SELECT 
(select COUNT(*) from t1 where f1 = 1),
(select COUNT(*) from t1 where f1 = 2),
(select COUNT(*) from t1 where f1 = 3),
(select COUNT(*) from t1 where f1 = 4)

2 টি নির্বাচনী বিবৃতি হাইলাইট করুন এবং প্রদর্শন আনুমানিক এক্সিকিউশন প্ল্যান আইকনে ক্লিক করুন। আপনি দেখতে পাবেন যে প্রথম বিবৃতিটি একটি টেবিল স্ক্যান করবে এবং দ্বিতীয়টি 4 করবে vious স্পষ্টতই একটি টেবিল স্ক্যান 4 এর চেয়ে ভাল।

একটি ক্লাস্টার্ড সূচক যুক্ত করা আকর্ষণীয় interesting যেমন

Create clustered index t1f1 on t1(f1);
Update Statistics t1;

উপরের প্রথম নির্বাচনটি একটি একক ক্লাস্টারড ইনডেক্স স্ক্যান করবে। দ্বিতীয় নির্বাচনটি 4 টি ক্লাস্টারড ইনডেক্স সিক্স করবে, তবে তারা এখনও একটি ক্লাস্টারড ইনডেক্স স্ক্যানের চেয়ে বেশি ব্যয়বহুল। আমি 8 মিলিয়ন সারি সহ একটি টেবিলে একই জিনিসটি চেষ্টা করেছি এবং দ্বিতীয় SELECT এখনও অনেক ব্যয়বহুল ছিল।


23

মাইএসকিউএল-এর জন্য এটি সংক্ষিপ্ত করা যেতে পারে:

SELECT distributor_id,
    COUNT(*) total,
    SUM(level = 'exec') ExecCount,
    SUM(level = 'personal') PersonalCount
FROM yourtable
GROUP BY distributor_id

1
এই প্রশ্নটিতে "ডিস্ট্রিবিউটর_আইডি দ্বারা" গ্রুপটি কি সত্যিই প্রয়োজনীয় ছিল? এটি ছাড়া
এটিও

2
@ ব্যবহারকারী1451111 মূল প্রশ্নটি এটি পেয়েছে তাই এটির উত্তরটি নিজেরাই প্রশ্নটির উপর নির্ভর করে
আল-মোতাহাফার

11

ঠিক আছে, আপনার যদি এটি অবশ্যই একটি ক্যোয়ারিতে থাকে তবে আপনি একটি ইউনিয়ন করতে পারতেন:

SELECT distributor_id, COUNT() FROM ... UNION
SELECT COUNT() AS EXEC_COUNT FROM ... WHERE level = 'exec' UNION
SELECT COUNT(*) AS PERSONAL_COUNT FROM ... WHERE level = 'personal';

বা, যদি আপনি প্রক্রিয়াজাতকরণের পরে করতে পারেন:

SELECT distributor_id, COUNT(*) FROM ... GROUP BY level;

আপনি প্রতিটি স্তরের জন্য গণনা পাবেন এবং মোটটি পাওয়ার জন্য তাদের সমস্তগুলি যোগ করতে হবে।


পাওয়া UNIONযখন একটি রিপোর্ট একাধিক দৃষ্টান্ত ধারণকারী উৎপাদিত খুব সহায়ক হতে COUNT(*)ফাংশন।
জেমস ও

ফলাফল দেখায় #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') FROM distributors UNION SELECT COUNT() AS EXEC_COUNT FROM distributors WHERE ' at line 1
ইসতিয়াক আহমেদ

সমস্ত প্রশ্ন থেকে ফিরে আসা কলামগুলির সংখ্যা, যার উপর একটি ইউনিয়ন প্রয়োগ করা হবে, সমান হওয়া উচিত। @ ইসতিয়াআহমেড সম্ভবত আপনার ত্রুটির পিছনে কারণ।
user1451111

ভবিষ্যতে এই উত্তরটির উপর যে হোঁচট খায় তার জন্য একটি নোট। এখানে বর্ণিত 'প্রসেসিংয়ের পরে' কৌশলটি সমস্যার কারণ হতে পারে যখন 'স্তর' কলামের মানগুলি শূন্য হয়। সেক্ষেত্রে সমস্ত উপ-গণনার যোগফল মোট সারির গণনার সমান হবে না।
ব্যবহারকারী1451111

6

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

select 'table1', count (*) from table1
union select 'table2', count (*) from table2
union select 'table3', count (*) from table3
union select 'table4', count (*) from table4
union select 'table5', count (*) from table5
union select 'table6', count (*) from table6
union select 'table7', count (*) from table7;

ফলাফল:

-------------------
| String  | Count |
-------------------
| table1  | 123   |
| table2  | 234   |
| table3  | 345   |
| table4  | 456   |
| table5  | 567   |
-------------------

1
a query that I created makes ...- কোথায় সেই জিজ্ঞাসা?
ইসতিয়াক আহমেদ

2
সমস্ত টেবিলগুলিতে ক্যালস কোথায় যুক্ত করবেন

3

ব্লুফিটের গৃহীত প্রতিক্রিয়ার ভিত্তিতে এটি ব্যবহার করে একটি যুক্ত উপদ্রব সহ OVER():

SELECT distributor_id,
    COUNT(*) total,
    SUM(case when level = 'exec' then 1 else 0 end) OVER() ExecCount,
    SUM(case when level = 'personal' then 1 else 0 end) OVER () PersonalCount
FROM yourtable
GROUP BY distributor_id

OVER()() তে কিছুই না দিয়ে ব্যবহার আপনাকে পুরো ডেটাসেটের জন্য মোট গণনা দেবে।


1

আমি মনে করি এটি আপনার পক্ষেও কাজ করতে পারে select count(*) as anc,(select count(*) from Patient where sex='F')as patientF,(select count(*) from Patient where sex='M') as patientM from anc

এবং আপনি এটি সম্পর্কিত টেবিল নির্বাচন এবং গণনা করতে পারেন select count(*) as anc,(select count(*) from Patient where Patient.Id=anc.PatientId)as patientF,(select count(*) from Patient where sex='M') as patientM from anc

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