2017-01-23 152 views
1

我有一个数据库充满了大量的“空”记录,我想摆脱那些孤儿记录。SQL - 在一个查询中同时选择“子”和“父”行

数据库是这样构成的;

  1. 包含真实项目(meta_value)
  2. 那就是 “链接” 到它的孩子父行(由它的meta_key)

一个子行 | 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”值,因为它是子级,但由下划线预先修正。

有什么方法来创建选择空的子记录一个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”,这里的家长有下划线。

+0

看起来像父行总是有一个meta_value,为什么不在你的where子句中使用它? 其中(wp_postmeta.meta_key LIKE '%ACF __%' AND wp_postmeta.meta_value LIKE '')或(wp_postmeta.meta_key LIKE '%ACF __%' AND wp_postmeta.meta_value <> '');然后根据您的喜好对输出进行排序 – iLikeMySql

+0

您想要的结果如何(请给出上述问题中的数据示例)? –

+0

你知道Navicat是否有共同的表格表达? –

回答

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 

在关系数据库中,有没有“之后”或“之前”这样的概念,除非你自己定义它,并将数据添加到实现该概念的表中(如日期时间戳,或顺序增加数字键或其他),如果没有这些工件,关系数据库表中的记录做不是有任何隐式的顺序

+0

看起来很有前途;它会显示来自我的表格的所有记录并带有下划线。 但我必须像我在我的初始职位过滤它们(字段必须包含“ACF__”并且也是空的)。 我可以使用这些过滤器进行查询并将它们连接到父级? '''SELECT \t * FROM \t wp_postmeta WHERE \t wp_postmeta.meta_key LIKE '%ACF __%' AND wp_postmeta.meta_value LIKE '' C JOIN wp_postmeta P于p.meta_key = '_' + C .meta_key''' 这会导致错误; '''你的SQL语法错误'c JOIN wp_postmeta p ON p.meta_key ='_'+ c.meta_key'at line 7''' –

+0

然后,你应该谷歌'加入'并阅读在上面。你修改后的查询在语法上不正确地使用了join,'Join'是数据库查询的基本工具,直到你学会使用它,你才会花费更多时间学习它。 。再看看输出,它应该显示来自表的父子记录的所有*对*行(每个*对*在单个显示的输出行中)。 –

+0

我尝试了两个例子,但它返回大约25000行 - 因为它们根本没有被过滤(当我用“foo”之类的东西替换“_”时,我得到了相同的25000结果)......看起来它什么都不做。 –

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."; 

    } 

?>