2013-08-19 46 views
6

Tôi hiện đang có một sql và php vấn đề mà tôi sử dụng báo cáo này để có được tất cả mọi thứ từ các dịch vụ cũng như bảng liên quan của nó:MySQL dấu phẩy tách giá trị

$db = $this->getDbo(); 
$query = $db->getQuery(true); 

// Select the required fields from the table. 
$query->select(
     $this->getState(
       'list.select', 'a.*' 
     ) 
); 

$query->from('`#__services_service` AS a'); 
$query->where("a.zone"); 

$query->select('zone.name AS zone, zone.description AS zone_description, zone.price AS zone_price, zone.interval_recommended AS interval_recommended'); 
$query->join('LEFT', '#__services_zones AS zone ON zone.id = a.zone'); 

$query->select('category.icon AS category'); 
$query->join('LEFT', '#__services_categories AS category ON category.id = a.category'); 

Nhưng trong bảng khu vực tôi tham gia, có dấu phẩy các giá trị tách biệt '1,2' và sau khi tạo một mảng kết hợp nơi tôi nhóm các dịch vụ vào vùng của chúng, dịch vụ số ít chỉ đi đến một vùng số ít, thay vì khi giá trị trong bảng là '1,2', nó phải ở cả hai khu vực ... Tôi có cảm giác đó là vì 'zone.name AS zone', bởi vì sau đó nó chỉ trả về một tên và nếu tôi nói 'zone AS zone', nó trả lại số được phân tách bằng dấu phẩy ...

Đây là cách tôi sắp xếp các mảng:

foreach($this->items as $item){ 
if(!isset($zones[ $item->zone ])) 
$zone_items[ $item->zone] = array(); 
$zone_items[ $item->zone ][] = $item; 

    $zones[$item->zone] = array(
     'zone' => $item->zone, 
     'zone_interval' => $item->interval_recommended, 
     'zone_description' => $item->zone_description, 
     'zone_price' => $item->zone_price, 
     'items' => $zone_items[$item->zone] 
    ); 

} 

và tôi hiển thị nó bằng cách:

<?php foreach($zones as $zone): ?> 
    <div class="row-fluid zones-page"> 
     <div class="row-fluid zone-title-block"> 
      <div class="span4 zone-name"><h1><?php echo $zone['zone']; ?></h1></div> 
      <div class="span7 zone-description"> 
       <?php echo $zone['zone_description']; ?> 
       <?php if($zone['zone_interval'] == 1): ?> 
        <span class="interval pull-right">Interval Recommended</span> 
       <?php endif; ?> 
      </div> 
     </div> 

     <?php foreach($zone['items'] as $items) :?> 
     <div class="row-fluid zone-services-contain"> 
      <div class="span1"><div class="zone-icon"><?php //echo $items->category; ?></div></div> 
      <div class="span11 zone-services"> 
       <h4><?php echo $items->name; ?></h4> 
       <div><?php echo $items->description; ?></div> 
      </div> 
     </div> 
     <?php endforeach; ?> 

     <div class="row-fluid zone-amount"> 
      only <div><?php echo 'R' . $zone['zone_price']; ?></div> 
     </div> 
    </div> 
    <div class="bicycle-divider"> 
     <div class="bicycle-icon"></div> 
    </div> 
<?php endforeach; ?> 

Any help is appreciated rất nhiều.

Bảng Services trông giống như:

enter image description here

Zones Bảng:

enter image description here

+0

Bảng trông như thế nào? –

+0

cái nào? .. dịch vụ, khu vực hoặc danh mục? –

+0

Bảng vùng. –

Trả lời

8

Đây là lý do tại sao mọi người thường sử dụng bảng liên kết để đối phó với nhiều-nhiều mối quan hệ như thế này. Một dịch vụ có thể có nhiều vùng, một vùng có thể có nhiều dịch vụ. Truy vấn một trường được phân cách bằng dấu phẩy và sử dụng trường đó trong một kết hợp với một bảng khác là khá khó khăn.

Bạn có hai tùy chọn, một trong số đó bao gồm thực hiện đúng cách và một tùy chọn cho phép bạn giữ mô hình cơ sở dữ liệu hiện tại của mình. Tôi đề nghị bạn làm đúng cách, nhưng để trả lời câu hỏi của bạn, tôi sẽ đi vào tùy chọn khác trước.

Chỉ cần tách các truy vấn của bạn. Chỉ cần có được lĩnh vực tách dấu phẩy trong truy vấn chính của bạn, sau đó chạy một truy vấn thứ hai để có được những tên zone:

SELECT * FROM zone WHERE id IN ($zoneIdsYouSelected) 

Bây giờ, nếu bạn đang làm việc với một danh sách, điều này có lẽ không phải là rất performant vì nó có nghĩa là bạn sẽ phải chạy một truy vấn cho danh sách và một truy vấn khác cho mỗi hàng. Một giải pháp thay thế là đưa tất cả các vùng vào một mảng và sau đó chọn từ đó bằng cách sử dụng PHP dựa trên $zoneIdsYouSelected. Bằng cách đó, bạn có thể nhận được ngay với 2 truy vấn thay vì nếu bạn đang lập kế hoạch để đạt được, như trái ngược với một truy vấn trên mỗi dòng dữ liệu.

Cách thích hợp liên quan đến việc tạo bảng liên kết chỉ chứa hai trường: zone_idservice_id. Nếu bạn sau đó tạo ra một truy vấn như thế này, bạn sẽ nhận được tất cả các tên trong một "lĩnh vực" trong tập kết quả của bạn:

SELECT s.id, s.name, s.description, s.price, s.category, s.ordering, 
     s.state, s.checked_out, s.checked_out_time, s.created_by, 
     GROUP_CONCAT(DISTINCT z.name ORDER BY z.name ASC SEPARATOR ', ') AS zones 
FROM  service s JOIN service_zone sz ON s.id = sz.service_id 
     JOIN zone z ON z.id = sz.zone_id 
GROUP BY s.id, s.name, s.description, s.price, s.category, s.ordering, 
     s.state, s.checked_out, s.checked_out_time, s.created_by 
ORDER BY s.id 

Có thể bạn sẽ phải tinh chỉnh truy vấn một chút, nhưng tôi hy vọng nó là rõ ràng. Hãy nhớ rằng GROUP_CONCAT không được hỗ trợ bởi tất cả các cơ sở dữ liệu nhưng MySQL có nó.

Một lần nữa, cả hai giải pháp đều có thể hoạt động tốt và có hiệu suất, nhưng có trường được phân cách bằng dấu phẩy sẽ tạo ra nhiều vấn đề hơn giống như trường hợp này. Tôi đề nghị bạn thay đổi cấu trúc cơ sở dữ liệu của bạn. Đọc về bình thường hóa cơ sở dữ liệu nếu bạn không quen thuộc với ý tưởng về các bảng liên kết.

+0

Cảm ơn bạn !, đừng bao giờ nghĩ đến việc liên kết các bảng ... Hãy làm điều đó đúng cách, dĩ nhiên là làm gì đó và biết sai? cảm ơn rất nhiều .. bệnh cố gắng nó thực sự nhanh chóng: D –