Laravel Eloquent - แตกต่าง () และ count () ทำงานร่วมกันไม่ถูกต้อง


99

ดังนั้นฉันจึงพยายามหาจำนวนของ pids ที่แตกต่างกันในแบบสอบถาม แต่ค่าที่ส่งกลับไม่ถูกต้อง

นี่คือสิ่งที่ฉันพยายามทำ:

$ad->getcodes()->groupby('pid')->distinct()->count()

สิ่งที่ส่งคืนค่า "2" ในขณะที่ค่าที่ควรส่งคืนควรเป็น "1"

เพื่อเป็นการแก้ปัญหาฉันกำลังทำสิ่งนี้:

count($ad->getcodes()->groupby('pid')->distinct()->get())

สิ่งที่ทำงานได้ดีและส่งกลับ "1"

มีกฎใดบ้างที่ไม่สามารถนับจำนวนและความแตกต่างในข้อความค้นหาเดียวกันได้ ฉันพบวิธีแก้ปัญหาแบบ "หนัก" ฉันต้องการให้ข้อความค้นหาเดิมใช้งานได้ :(


คุณมีอะไรในตารางตัวอย่างในฐานข้อมูล และคุณต้องการบรรลุอะไร? ตอนนี้คุณน่าจะได้รับจำนวนค่าที่แตกต่างกันในpidคอลัมน์ดังนั้นหากคุณมีในตาราง 2 ระเบียน - หนึ่งที่มี pid 1 วินาทีกับ pid 2 การนับควรส่งกลับ 2
Marcin Nabiałek

คุณสามารถแทนที่ get ด้วยการนับด้วยวิธีนี้: $count = DB::table('tablename')->count(DB::raw('DISTINCT pid')); สามารถทำได้: DB::table('tablename')->distinct('pid')->count('pid');
bharat

คำตอบ:


129

สิ่งต่อไปนี้ควรใช้งานได้

$ad->getcodes()->distinct('pid')->count('pid');

2
มีปัญหาที่คล้ายกันและดูเหมือนว่าgroupByจะไม่ใช้เคล็ดลับ
jeteon

8
ความโดดเด่นไม่ใช้ข้อโต้แย้งใด ๆ การเรียกความแตกต่าง () เมื่อสร้างแบบสอบถามของคุณเพียงแค่ตั้งค่าบูลีนที่ได้รับการป้องกันเป็นจริงอาร์กิวเมนต์จะถูกละเว้น
Matt McDonald

บน L5.1 และยังใช้งานไม่ได้ การใช้count()ดูเหมือนจะปิดใช้งานหรือปล่อยไฟล์distinct(). ใช้groupBy()ตามที่อธิบายไว้ตลอดคำถาม แก้ไข: ฉันพบว่าแม้groupBy()จะให้ความแตกต่างcount()เมื่อเทียบกับget()ตามด้วยการนับอาร์เรย์ผลลัพธ์
Jason

@ Jason ฉันได้สังเกตเช่นเดียวกับคุณ ดูคำตอบของฉันสำหรับวิธีแก้ปัญหา
Zoon

21
distinct()ฟังก์ชั่นใช้เวลาไม่มีข้อโต้แย้ง คุณสามารถเปลี่ยน$ad->getcodes()->distinct()->count('pid');เป็นผลลัพธ์เดียวกันได้
Trevor Gehman

26

คำตอบทั่วไปที่จะช่วยฉันประหยัดเวลาและหวังว่าคนอื่น ๆ :

ไม่ทำงาน (ส่งคืนจำนวนแถวทั้งหมด):

DB::table('users')
            ->select('first_name')
            ->distinct()
            ->count();

การแก้ไข:

DB::table('users')
            ->distinct()
            ->count('first_name');

17

มีใครเจอโพสต์นี้และไม่พบคำแนะนำอื่น ๆ ในการทำงาน?

อาจจำเป็นต้องใช้แนวทางที่แตกต่างกันทั้งนี้ขึ้นอยู่กับข้อความค้นหาที่ระบุ ในกรณีของฉันฉันต้องนับผลลัพธ์ของ a GROUP BYเช่น

SELECT COUNT(*) FROM (SELECT * FROM a GROUP BY b)

หรือใช้COUNT(DISTINCT b):

SELECT COUNT(DISTINCT b) FROM a

หลังจากงง ๆ ฉันก็ตระหนักว่าไม่มีฟังก์ชัน Laravel ในตัวสำหรับสิ่งเหล่านี้ ดังนั้นวิธีแก้ปัญหาที่ง่ายที่สุดคือใช้DB::rawกับcountวิธีนี้

$count = $builder->count(DB::raw('DISTINCT b'));

โปรดจำไว้ว่าไม่ได้ใช้ก่อนที่จะเรียกgroupBy countคุณสามารถสมัครได้ในgroupByภายหลังหากต้องการรับแถว


$ builder มาจากไหน?
Andrew

1
@Andrew ตัวสร้างแบบสอบถาม Laravel ที่คุณใช้สำหรับแบบสอบถาม ตัวอย่างเช่นวัตถุ Eloquent$books = Book::where(...)->count(...)
Zoon

->count(DB::raw('DISTINCT b'))สร้างแบบสอบถาม SQL เดียวกันกับ->distinct()->count('b')
Trevor Gehman

5

ฉันมีปัญหาคล้าย ๆ กันและพบวิธีแก้ไข

ปัญหาคือวิธีที่ตัวสร้างแบบสอบถามของ Laravel จัดการกับข้อมูลรวม ใช้ผลลัพธ์แรกที่ส่งคืนแล้วส่งกลับค่า 'รวม' โดยปกติจะใช้ได้ดี แต่เมื่อคุณรวมการนับกับ groupBy คุณจะส่งคืนจำนวนต่อรายการที่จัดกลุ่ม ดังนั้นการรวมของแถวแรกจึงเป็นเพียงการนับของกลุ่มแรก (จึงมีโอกาสต่ำเช่น 1 หรือ 2)

ดังนั้นจำนวนของ Laravel จึงหมดลง แต่ฉันรวมตัวสร้างแบบสอบถาม Laravel กับ SQL ดิบเพื่อให้ได้ผลลัพธ์ที่จัดกลุ่มของฉันอย่างถูกต้อง

สำหรับตัวอย่างของคุณฉันคาดว่าสิ่งต่อไปนี้ควรใช้งานได้ (และให้คุณหลีกเลี่ยงการได้รับ):

$query = $ad->getcodes()->groupby('pid')->distinct();
$count = count(\DB::select($query->toSql(), $query->getBindings()));

หากคุณต้องการให้แน่ใจว่าคุณไม่เสียเวลาในการเลือกคอลัมน์ทั้งหมดคุณสามารถหลีกเลี่ยงสิ่งนั้นได้เมื่อสร้างแบบสอบถาม

 $query = $ad->select(DB::raw(1))->getcodes()->groupby('pid')->distinct();

4

ฉันเจอปัญหาเดียวกัน

หากคุณติดตั้งแถบดีบัก laravel คุณจะเห็นข้อความค้นหาและมักจะเห็นปัญหา

$ad->getcodes()->groupby('pid')->distinct()->count()

เปลี่ยนไป

$ad->getcodes()->distinct()->select('pid')->count()

คุณต้องตั้งค่าที่จะส่งคืนเป็นค่าที่แตกต่างกัน หากคุณไม่ได้ตั้งค่าฟิลด์ที่เลือกระบบจะส่งคืนคอลัมน์ทั้งหมดในฐานข้อมูลและทั้งหมดจะไม่ซ้ำกัน ดังนั้นตั้งค่าการสืบค้นให้แตกต่างกันและเลือกเฉพาะคอลัมน์ที่ประกอบเป็นค่า "เฉพาะ" ที่คุณอาจต้องการเพิ่ม ->select('pid','date')เพื่อรับค่าที่ไม่ซ้ำกันทั้งหมดสำหรับผู้ใช้ในหนึ่งวัน


4

คุณสามารถใช้วิธีต่อไปนี้เพื่อรับข้อมูลเฉพาะตามความต้องการของคุณดังต่อไปนี้

$data = $ad->getcodes()->get()->unique('email');

$count = $data->count();

หวังว่าจะได้ผล


1

จะไม่ทำงานนี้?

$ad->getcodes()->distinct()->get(['pid'])->count();

ดูการสนทนาที่นี่ ..


3
นี่ไม่ใช่วิธีแก้ปัญหาที่ดีเนื่องจากการget()โทรจะดำเนินการค้นหาและส่งคืนผลลัพธ์จากฐานข้อมูลจากนั้นจึงcount()รันบนคอลเล็กชัน
Trevor Gehman

1
$solution = $query->distinct()
            ->groupBy
            (
                [
                    'array',
                    'of',
                    'columns',
                ]
            )
            ->addSelect(
                [
                    'columns',
                    'from',
                    'the',
                    'groupby',
                ]
            )
            ->get();

โปรดจำไว้ว่ากลุ่มตามเป็นทางเลือกซึ่งควรใช้งานได้ในกรณีส่วนใหญ่เมื่อคุณต้องการให้กลุ่มนับโดยเพื่อแยกค่าที่เลือกที่ซ้ำกัน addSelect เป็นวิธีการอินสแตนซ์ตัวสร้างแบบสอบถาม


0

ความแตกต่างอย่าใช้อาร์กิวเมนต์เนื่องจากเพิ่ม DISTINCT ในแบบสอบถาม sql ของคุณอย่างไรก็ตามคุณอาจต้องกำหนดชื่อคอลัมน์ที่คุณต้องการเลือกที่แตกต่างด้วย ดังนั้นหากคุณมีความ Flight->select('project_id')->distinct()->get()เท่าเทียมกันSELECT DISTINCT 'project_id' FROM flightsและตอนนี้คุณสามารถเพิ่มตัวปรับแต่งอื่น ๆ เช่น count () หรือแม้แต่คำค้นหาที่คมคายแบบดิบๆ


0

จากเอกสาร Laravel สำหรับการสืบค้นดิบฉันสามารถนับจำนวนช่องที่เลือกเพื่อใช้กับรหัสนี้ในรุ่นผลิตภัณฑ์ได้

public function scopeShowProductCount($query)
{
    $query->select(DB::raw('DISTINCT pid, COUNT(*) AS count_pid'))
          ->groupBy('pid')
          ->orderBy('count_pid', 'desc');
}

ซุ้มนี้ทำงานเพื่อให้ได้ผลลัพธ์เดียวกันในตัวควบคุม:

$products = DB::table('products')->select(DB::raw('DISTINCT pid, COUNT(*) AS count_pid'))->groupBy('pid')->orderBy('count_pid', 'desc')->get();

การถ่ายโอนข้อมูลผลลัพธ์สำหรับทั้งสองแบบสอบถามเป็นดังนี้:

#attributes: array:2 [
  "pid" => "1271"
  "count_pid" => 19
],
#attributes: array:2 [
  "pid" => "1273"
  "count_pid" => 12
],
#attributes: array:2 [
  "pid" => "1275"
  "count_pid" => 7
]

-2

สิ่งนี้ใช้ได้ผลสำหรับฉันดังนั้นลองสิ่งนี้: $ ad-> getcodes () -> แยก ('pid') -> count ()


สวัสดียินดีต้อนรับสู่ SO เมื่อตอบคำถามโปรดระบุข้อมูลเพิ่มเติมเกี่ยวกับรหัสที่คุณให้มา การมีส่วนร่วมเช่นนี้ยินดีต้อนรับ แต่คนอื่น ๆ ในอนาคตอาจได้รับประโยชน์จากคำอธิบายการยิง
Deepend

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.