MYSQL php:如果找不到“WHERE IN”id,则查询多行并返回值

时间:2016-07-24 07:02:45

标签: php mysql wordpress

我正在开发一个管理事件的wordpress网站。

问题是我需要在单个查询中从相应的ID中获取一些事件标题名称。我试图从单个MYSQL查询中获取多行,使用“WHERE IN ({$IDs})”可以正常工作:

$events_implode = implode(',',$events);
$events_titles = $wpdb->get_results("SELECT `title` FROM `wp_events` WHERE `id` in ({$events_implode}) ORDER BY FIELD(id,{$events_implode}",ARRAY_A);

但是,如果在查询中找不到其中一个$ ID而不返回任何内容,我需要它返回一个值/字符串。

实施例: 如果$events_implode类似于:318,185,180,377,则ID为180& 185不存在(例如被删除),我找回了318&的事件标题。仅限377:

Array
(
    [0] => Array
        (
            [title] => Title 1
        )

    [1] => Array
        (
            [title] => Title 4
        )

)

虽然我需要它来返回类似的内容:

Array
(
    [0] => Array
        (
            [title] => Title 1
        )

    [3] => Array
        (
            [title] => Title 4
        )

)

我试过了IFNULL:

$events_titles = $wpdb->get_results("SELECT IFNULL( (SELECT `title` FROM `wp_events` WHERE `id` in ({$events_implode}) ORDER BY FIELD(id,{$events_implode}) ),'not found')",ARRAY_A);

但由于查询返回多行,我收到错误消息:

"mysqli_query(): (21000/1242): Subquery returns more than 1 row"

有解决方法吗? 非常感谢!

3 个答案:

答案 0 :(得分:2)

你也可以通过查询id而不仅仅是标题来实现这一点:

SELECT id, title FROM ... etc

然后您的结果数组将如下所示(对于示例数据)

array(
    0 => array("id" => 318, "title" => "title for 318"),
    1 => array("id" => 377, "title" => "title for 377")
)

但是,在您已经拥有的 $ events 数组的帮助下,这可以转换为您需要的内容:

foreach($event_titles as $row) {
    $hash[array_search($row['id'], $events)] = $row['title'];
};

$events_titles = $hash;

现在数组看起来像这样(对于示例数据):

array(
    0 => array("title" => "title for 318"),
    3 => array("title" => "title for 377")
)

注意:转换也可以在没有显式循环的情况下完成:

$ids = array_intersect($events, array_column($event_titles, 'id'));
$event_titles = array_combine(array_keys($ids), array_column($event_titles, 'title'));

替代

以上可能是针对您的案例的最佳解决方案,但您也可以动态构建查询以实现此目的:

$subsql = implode(
    ' UNION ALL ', 
    array_map(function ($event) { return "SELECT $event AS id"; }, $events)
); 

$sql = "SELECT    wp_events.title 
        FROM      ($subsql) AS eid
        LEFT JOIN wp_events ON wp_events.id = eid.id
        ORDER BY  eid.id";

$events_titles = $wpdb->get_results($sql, ARRAY_A);

$ subsql 的值将如下(例如数据):

SELECT 318 AS id UNION ALL
SELECT 185 AS id UNION ALL
SELECT 180 AS id UNION ALL
SELECT 377 AS id

$ events_titles 的值将是一个数组,每个事件都有一个条目,无论它是否匹配。所以对于你给出的例子,你会得到这个结果:

array(
    0 => array("title" => "title for 318"),
    1 => array("title" => null), // because no match with 185
    2 => array("title" => null), // because no match with 180
    3 => array("title" => "title for 377")
)

所以你现在可以只测试null。如果另外您要删除null条目而不更改数组中的索引(0 ... 3),请执行以下操作:

$event_titles = array_filter($event_titles, function ($title) { return $title; });

这将给你(在例子中):

array(
    0 => array("title" => "title for 318"),
    3 => array("title" => "title for 377")
)

答案 1 :(得分:1)

使用in子句似乎不可能,但您可以使用union form dual

构建一个dinamic查询
"SELECT  t.index, a.`title` 
 FROM `wp_events` as a 
 INNER JOIN ( select  1 as index , 318 as id
             from dual 
             union 
             select 2, 185
             from dual
             union 
             select 3, 180
             from dual
             union 
             select 4, 377
             from dual                 

             ) t  on t.id = b.id
ORDER BY t.index"

答案 2 :(得分:0)

不,没有办法。 mysql-query返回的数组与您为查询提供的implode-array无关。可能有选项可以实现这一点(创建一个临时表,用键填充它,从表连接到事件表的左连接),但请不要这样做,因为这是不好的做法和坚果KISS(保持简单,愚蠢)。

简单的问题是,你为什么要这样做?