簡體   English   中英

如何重寫我的SQL查詢,以便它以特定格式(使用mysql或php)返回值?

[英]How can I rewrite my sql query so that it returns the values in a specific format (using mysql or php)?

我有一個叫做number的表:

number_id  |  number_name
   1            aaaa
   2            bbbb
   3            cccc
   4            dddd
   5            eeee
   6            ffff

(它只包含6個條目)

我還有一個叫做texts的表格:

text_id  |  start_time  |  number_id  |  text_content
   1        some date1  |     2       |    blabla1
   2        some date2  |     1       |    blabla2
   3        some date3  |     2       |    blabla3
   4        some date4  |     3       |    blabla4
   5        some date5  |     4       |    blabla5
   6        some date6  |     6       |    blabla6
  etc.

(它包含很多條目)。

現在,當我正在進行這樣的查詢時:

SELECT
   * 
FROM
   (SELECT
      DATEDIFF(now(),
      start_time) AS days_ago,
      number_id,
      COUNT(text_id) AS num_texts 
   FROM
      TEXTS 
   WHERE
      start_time BETWEEN  DATE_SUB(NOW(), INTERVAL 100 DAY) AND NOW() 
   GROUP BY
      DATE(start_time),
      number_id) AS temp

它使用number_id返回每個地方過去100天每天的文本數量。 結果如下:

在此輸入圖像描述

當我將它編碼為json時,我得到:

[{"days_ago":"19","number_id":"1","num_texts":"179"},
{"days_ago":"19","number_id":"5","num_texts":"1"},
{"days_ago":"18","number_id":"1","num_texts":"61"},
{"days_ago":"18","number_id":"2","num_texts":"1"},
{"days_ago":"18","number_id":"5","num_texts":"1"},
{"days_ago":"18","number_id":"6","num_texts":"3"},
{"days_ago":"17","number_id":"3","num_texts":"1"},
{"days_ago":"8","number_id":"1","num_texts":"2"},
{"days_ago":"8","number_id":"2","num_texts":"2"},
{"days_ago":"7","number_id":"4","num_texts":"1"},

我想寫一個不同的查詢,或更改現有的查詢。 有沒有辦法編寫一個查詢,將以下列方式返回我的數據:

[{"days_ago": "7", "number_id" : "1", "num_texts" : "18", "number_id" : "2", "num_texts" : "12", "number_id" : "3", "num_texts" : "12" , ... , "number_id" : "6", "num_texts" : "1"},
{"days_ago": "6", "number_id" : "1", "num_texts" : "18", "number_id" : "2", "num_texts" : "12", "number_id" : "3", "num_texts" : "12" , ... , "number_id" : "6", "num_texts" : "1"},
{"days_ago": "5", "number_id" : "1", "num_texts" : "18", "number_id" : "2", "num_texts" : "12", "number_id" : "3", "num_texts" : "12" , ... , "number_id" : "6", "num_texts" : "1"},
{"days_ago": "4", "number_id" : "1", "num_texts" : "18", "number_id" : "2", "num_texts" : "12", "number_id" : "3", "num_texts" : "12" , ... , "number_id" : "6", "num_texts" : "1"},
{"days_ago": "3", "number_id" : "1", "num_texts" : "18", "number_id" : "2", "num_texts" : "12", "number_id" : "3", "num_texts" : "12" , ... , "number_id" : "6", "num_texts" : "1"},
{"days_ago": "2", "number_id" : "1", "num_texts" : "18", "number_id" : "2", "num_texts" : "12", "number_id" : "3", "num_texts" : "12" , ... , "number_id" : "6", "num_texts" : "1"},
{"days_ago": "1", "number_id" : "1", "num_texts" : "18", "number_id" : "2", "num_texts" : "12", "number_id" : "3", "num_texts" : "12" , ... , "number_id" : "6", "num_texts" : "1"}] 

基本上每行應該有6個number_id每一行的days_ago和值num_texts的信息。 我需要限制此查詢僅過去7天,所以我知道我可以在這里修改它:

BETWEEN DATE_SUB(NOW(), INTERVAL 100 DAY) AND NOW()

並將100改為7,但有可能以某種方式得到這種特定格式的其他信息嗎?

哦還有一件事 - 我正在從php調用這個查詢,所以如果它更容易在php中以某種方式解析它並作為json返回,這也是一個選項。

非常感謝任何提示家伙!

=========編輯:

正如@AlexBlex指出的那樣 - 我提出的json結構可能無效,因為有多次使用相同的鍵名。 為了幫助您更好地理解我的問題 - http://thevectorlab.net/flatlab/morris.html這里是morris js圖表的例子。 我希望在該示例中將圖表生成為名為Quarterly Apple iOS device unit sales的圖表。 在水平線上我想要日期( days ago ),在垂直線上我需要num_texts。 我希望有6行,每行代表不同的number_id。

假設您的number具有永遠不會改變的這6個固定值,則可以通過鏈接6個texts表副本(或創建6個視圖)來實現。

但是如果你通過跟蹤days_ago更改並添加新的JSON記錄來在php中執行它可能會更加清晰。 您還必須確保沒有number_id被跳過,用於添加一個零值num_texts任何跳過。

另外,示例偽代碼:

$days_ago=0;
while ([read_records]) {
    if (record['days_ago']!=$days_ago {
        $days_ago!=0 [Close line]
        $days_ago=record['days_ago'];
        [Add new line]
        [Add days_ago field]  }
    [Add number_id and num_texts fields]
}
[Close line]

第二個編輯,視圖解決方案:

如果view_1是我在下面描述的視圖並且view_2number_id 2的視圖,你可以將它們鏈接如下:

SELECT view_1.days_ago, view_1.num_texts AS num_texts1, view_2.num_texts AS num_texts2
FROM view_1 INNER JOIN view_2 ON view_1.days_ago=view_2.days_ago

如果每個days_ago所有number_id都有條目,則此willo只能正常工作,否則您將只需創建days_ago的視圖並使用LEFT / RIGHT聯接來加入number_id視圖。

您可以使用數據透視表執行此操作:

SELECT
   days_ago,
   SUM(IF(number_id = 1, num_texts, 0)) as num_1_texts,
   SUM(IF(number_id = 2, num_texts, 0)) as num_2_texts,
   SUM(IF(number_id = 3, num_texts, 0)) as num_3_texts,
   SUM(IF(number_id = 4, num_texts, 0)) as num_4_texts,
   SUM(IF(number_id = 5, num_texts, 0)) as num_5_texts,
   SUM(IF(number_id = 6, num_texts, 0)) as num_6_texts
FROM
   (SELECT
      DATEDIFF(now(),start_time) AS days_ago,
      number_id,
      COUNT(text_id) AS num_texts 
   FROM
      TEXTS 
   WHERE
      start_time BETWEEN  DATE_SUB(NOW(), INTERVAL 100 DAY) AND NOW() 
   GROUP BY
      DATE(start_time),
      number_id)

GROUP BY days_ago;

如果數字量是任意的,您可以使用您正在使用的任何語言生成字段列表。

在PHP中:

$selectFields = '';
$numbers = 10;
$separator = ''
for($i=1; $i<=$numbers; $i++) {
    $selectFields .= $separator . "SUM(IF(number_id = {$i}, num_texts, 0)) as num_{$i}_texts";
    $separator = ',';
}

$query = "
    SELECT
    days_ago,
    $selectFields
    FROM
       (SELECT
          DATEDIFF(now(),start_time) AS days_ago,
          number_id,
          COUNT(text_id) AS num_texts 
       FROM
          TEXTS 
       WHERE
          start_time BETWEEN  DATE_SUB(NOW(), INTERVAL 100 DAY) AND NOW() 
       GROUP BY
          DATE(start_time),
          number_id)
    ORDER BY days_ago      
    GROUP BY days_ago;
";

當然有人指出,你的JSON中有重復的id,但它可以很容易地表示為:

[{days_ago: "1", numbers: [{"id" : "1", "num_texts" : "12"},...{"id": "n", "num_texts": "999"}],
{days_ago: "2", numbers: [{"id" : "1", "num_texts" : "12"},...{"id": "n", "num_texts": "999"}],
...

或者Morris.js期待的任何格式。 您可以在一個軸上使用日期,在另一個軸上使用num_texts。 您可能還需要處理特定日期沒有活動的情況。

這樣的事情怎么樣:

    <?php
        $query = "SELECT DATEDIFF(now(), start_time) AS days_ago, number_id, COUNT(text_id) AS num_texts
                    FROM TEXTS 
                    WHERE start_time BETWEEN  DATE_SUB(NOW(), INTERVAL 100 DAY) AND NOW() 
                    GROUP BY DATE(start_time), number_id";
        $stmt = $conn->prepare($query);
        $stmt->execute();

        // convert to 2D array
        while ($result = $stmt->fetch(PDO::FETCH_ASSOC))
        {
            if (!isset($res_ar[$result['days_ago']]))
            {
                $res_ar[$result['days_ago']] = array_fill(1, 6, 0);
            }

            $res_ar[$result['days_ago']][$result['number_id']] = $result['num_texts'];
        }

        // fill-in empty rows
        for ($x = 1; $x <= 7; $x++)
        {
            if (!array_key_exists($x, $res_ar))
            {
                $res_ar[$x] = array_fill(1, 6, 0);
            }
        }

        // convert to nested arrays
        foreach ($res_ar as $days_ago => $texts)
        {
            $res_out[$days_ago]['days_ago'] = $days_ago;
            foreach ($texts as $id => $count)
            {
                $res_out[$days_ago]['counts'][$id]['number_id'] = $id;
                $res_out[$days_ago]['counts'][$id]['num_texts'] = $count;
            }
        }

        // convert nested PHP arrays to nested JSON object
        $json = json_encode($res_out);
    ?>

我實際上沒有運行這個,所以我不保證bug,但它至少應該讓你開始。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM