MYSQL php:查询多行并返回值if";其中IN”;找不到id


MYSQL php: query multiple rows and return value if "WHERE IN" id not found

我正在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"

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

您可以通过查询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的值如下(例如data):

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

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

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。如果您还想在不更改数组中的索引(0…3)的情况下删除null条目,请执行以下操作:

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

这将给您(在示例中):

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

使用in子句似乎是不可能的,但您可以使用并集形式的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"

不,没有办法。mysql查询返回的数组与您提供给查询的内爆数组无关。可能有一些选项可以实现这一点(创建一个临时表,用键填充它,从该表向左联接到事件表),但请不要这样做,因为这是一种糟糕的做法,而且会破坏KISS(保持简单,愚蠢)。

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