SQL - 在单个查询中选择“子”和“父”行

时间:2017-01-23 13:26:14

标签: mysql sql database

我有一个填充了大量“空”记录的数据库,我想摆脱那些孤立的记录。

数据库结构如下;

  1. 包含真实条目(meta_value)
  2. 子行
  3. 与其子项“链接”的父行(通过它的meta_key)
  4. | meta_id post_id meta_key meta_value | | | | 011 301 ACF__P_01_01 Foo | | 012 309 _ACF__P_01_01 field_5874d5 | | 013 321 ACF__P_01_02 | | 014 316 _ACF__P_01_02 field_54290a | | 015 119 ACF__P_01_03 Bar | | 016 101 _ACF__P_01_03 field_a04a88 | | 017 119 ACF__P_01_03 | | 018 101 _ACF__P_01_03 field_a04a88 | | 019 149 ACF__P_01_03 | | 020 111 _ACF__P_01_03 field_a04a88 | | 021 169 ACF__P_01_03 Foo Bar | | 022 171 _ACF__P_01_03 field_a04a88 |

    使用像这样的查询选择所有(空)“子”行很容易;

    SELECT
        *
    FROM
        wp_postmeta
    WHERE
        wp_postmeta.meta_key LIKE '%ACF__%'
    AND
        wp_postmeta.meta_value LIKE ''
    

    但是这个查询只获取(空)“子”行,而不是它们的“父”行。

    有两个逻辑条件将父级绑定到子级;

    1. 第一行始终是孩子,紧随其后的
    2. 父行与其子项具有相同的“ meta_key ”值,但由下划线预先修复
    3. 有没有办法创建一个SQL查询来选择空的子记录(就像我上面做的那样)它也是父项?

      我更喜欢单个查询来获取它们 - 但是当这不可能时,我也可以运行两个查询(第一个获取父项,第二个获取空子项,我猜)。

      我使用 Navicat 进行数据库管理,因此它必须是纯SQL - 没有PHP。

      查询应该像这样吐出结果;

      | meta_id post_id meta_key meta_value | | | | 013 321 ACF__P_01_02 | | 014 316 _ACF__P_01_02 field_54290a | | 017 119 ACF__P_01_03 | | 018 101 _ACF__P_01_03 field_a04a88 | | 019 149 ACF__P_01_03 | | 020 111 _ACF__P_01_03 field_a04a88 |

      因此两个空子项(“meta_value”中没有值)和它的父项(两者都具有相同的“meta_key”,其中父项具有下划线。

2 个答案:

答案 0 :(得分:3)

使用自我加入

Select *
from wp_postmeta c
   join wp_postmeta p
      on p.meta_key = '_' + c.meta_key

以上只会获取父对子记录的“对”。如果没有孩子的父母可以(我认为没有父母的孩子是不可能的),并且你希望所有的父母,包括没有孩子的父母,都使用外连接

Select *
from wp_postmeta p
   left join wp_postmeta c
      on '_' + c.meta_key = p.meta_key 

在关系数据库中,没有“after”或“before”之类的概念,除非您自己定义并将数据添加到实现该概念的表中(如datetimestamp,或顺序增加数字键,或其他。)这样的工件,关系数据库表中的记录 有任何隐含的顺序。

答案 1 :(得分:0)

使用PHP我能够解决它。我迭代查询的第一个结果(获取所有空子项)并在循环内获取该子项之后的每一行。

但那是PHP - 我想要纯SQL:)

<?php

$connection = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

  if ($connection -> connect_errno > 0) {

    die ("Unable to connect to database [" . $connection->connect_error . "]");

  }

$query_1 = "SELECT * FROM `wp_postmeta` WHERE `meta_key` LIKE '%ACF%__' AND `meta_value` LIKE ''";

  if (!$result_1 = $connection -> query($query_1)) {

    die ("There was an error running query[" . $connection -> error . "]");

  }

  if ($result_1) {

    $i = 0;

    echo "<h2>ACF - empty fields</h2>";
    echo "<table border=1 cellpadding=4 cellspacing=0 width=800>";
    echo "<tr style='background:#eee;font-weight:bold;'><td>row</td><td>meta_id</td><td>post_id</td><td>meta_key</td><td>meta_value</td></tr>";

      while ($row_1 = $result_1 -> fetch_assoc()) {

        $i++;
        echo "<tr>";
        echo "<td width=100>" . sprintf('%03d', $i) . "</td>";
        echo "<td width=100 style='background:#aaa;color:#fff;font-weight:bold;'>" . $row_1["meta_id"] . "</td>";
        echo "<td width=100>" . $row_1["post_id"] . "</td>";
        echo "<td width=100>" . $row_1["meta_key"] . "</td>";
        echo "<td width=500>" . $row_1["meta_value"] . "</td>";
        echo "</tr>";

        $query_2 = "SELECT * FROM `wp_postmeta` WHERE `meta_id` = " . ($row_1["meta_id"] + 1);

          if (!$result_2 = $connection -> query($query_2)) {

            die ("There was an error running query[" . $connection -> error . "]");

          }

          while ($row_2 = $result_2 -> fetch_assoc()) {

            $i++;
            echo "<tr>";
            echo "<td width=100>" . sprintf('%03d', $i) . "</td>";
            echo "<td width=100 style='background:#aaa;color:#fff;font-weight:bold;'>" . $row_2["meta_id"] . "</td>";
            echo "<td width=100>" . $row_2["post_id"] . "</td>";
            echo "<td width=100>" . $row_2["meta_key"] . "</td>";
            echo "<td width=500>" . $row_2["meta_value"] . "</td>";
            echo "</tr>";

          }

        mysqli_free_result($result_2);

      }

    mysqli_free_result($result_1);

    echo "</table>";

  } else {

    echo "No entries found.";

  }

?>

- 编辑 -

这个PHP代码更好,我想......它只使用2个查询并迭代第一个...

它完美无缺,但仍然不是纯SQL - 我想摆脱PHP ......

<?php

/* --------------------------------------------------- */

$connection = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

  if ($connection -> connect_errno > 0) {

    die ("Unable to connect to database [" . $connection->connect_error . "]");

  }

/* --------------------------------------------------- */

$query = "SELECT `meta_id` FROM `wp_postmeta` WHERE `meta_key` LIKE '%ACF%__' AND `meta_value` LIKE ''";

  if (!$result = $connection -> query($query)) {

    die ("There was an error running query[" . $connection -> error . "]");

  }

  if ($result) {

    $array = array();

      while ($row = $result -> fetch_assoc()) {

        $array[] = $row["meta_id"];
        $array[] = $row["meta_id"] + 1;

      }

    mysqli_free_result($result);

/* --------------------------------------------------- */

    $query = "SELECT * FROM `wp_postmeta` WHERE `meta_id` IN (" . implode(",", array_map("intval", $array)) . ")";

      if (!$result = $connection -> query($query)) {

        die ("There was an error running query[" . $connection -> error . "]");

      }

      if ($result) {

        $i = 0;

        echo "<h2>ACF - empty fields</h2>";
        echo "<table>";
        echo "<tr><td>record</td><td>meta_id</td><td>post_id</td><td>meta_key</td><td>meta_value</td></tr>";

          while ($row = $result -> fetch_assoc()) {

            $i++;
            echo "<tr>";
            echo "<td>" . sprintf('%03d', $i) . "</td>";
            echo "<td>" . $row["meta_id"] . "</td>";
            echo "<td>" . $row["post_id"] . "</td>";
            echo "<td>" . $row["meta_key"] . "</td>";
            echo "<td>" . $row["meta_value"] . "</td>";
            echo "</tr>";

          }

        mysqli_free_result($result);

        echo "</table>";

          if (isset($_GET["delete"])) {

            echo "<span>all records deleted</span>";

          } else {

            echo "<a href='?delete'>delete empty records</a>";

          }

      }

/* --------------------------------------------------- */

  } else {

    echo "No entries found.";

  }

?>
相关问题