如何从 MySQL 中的比较和空检查指定 ORDER BY?
How to specify an ORDER BY from comparisons and null checks in MySQL?
我有两个 tables feed_old(默认数据)和 feed_new(新数据),其中 cron 作业将每天 运行 并且仅更新 feed_new table 与当前信息
Cron 作业
$url = "localhost/test.xml";
$xml = simplexml_load_file($url);
$this->db->query("TRUNCATE TABLE feed_new");
$date = date('Y-m-d H:i:s');
foreach($xml->Product as $item)
{
$data = array(
'product_code' => $item->ProductCode,
'name' => $item->Name,
'price' => $item->RetailCurrentPrice,
'stock' => (int)$item->Stock,
'manufacture' => '1',
'date_updated' => $date
);
$update_status = $this->model_price->check_price($data);
}
型号
public function check_price($data)
{
if($data) {
$insert = $this->db->insert('feed_new', $data);
return ($insert == true) ? true : false;
}
}
自此一切正常
当我比较 feed_new 与 feed_old 并获取所有更改并显示所有记录时,问题就来了
比较 feed_new 与 feed_old 之后,我想从 table 中提取所有记录并按级别排序
级别 1 - 如果产品有不同的价格 feed_new.price <> feed_old.price
2 级 - 如果来自 feed_old 的产品在 feed_new 中不存在(这意味着产品不再受支持)
3 级 - 如果来自 feed_new 的产品在 feed_old 中不存在(这意味着产品是新的)
4 级 - 其余结果
比较查询
SELECT fn.name AS name_new, fo.date_updated, fo.id, fo.name,fo.price,fo.product_code, fn.product_code AS product_code_new, fo.stock, fn.price AS price_new, fn.stock AS stock_new, fn.date_updated AS date_updated_new
FROM feed_old fo
LEFT JOIN feed_new fn ON fo.product_code = fn.product_code
UNION ALL
SELECT fn.name AS name_new, fo.date_updated, fo.id, fo.name,fo.price,fo.product_code, fn.product_code AS product_code_new, fo.stock, fn.price AS price_new, fn.stock AS stock_new, fn.date_updated AS date_updated_new
FROM feed_old fo
RIGHT JOIN feed_new fn ON fn.product_code = fo.product_code
WHERE fo.product_code IS NULL OR fn.name IS NULL ORDER BY COALESCE(price <> price_new, name_new is NULL, product_code IS NULL) DESC
问题是级别 - 3 总是显示在最后一条记录中,我的意思是在级别 - 4 之后
在我下面的工作示例中,您可以看到 name_new -> test3 位于 table 的底部,而此时应该位于第 3 个位置
如何按以上级别订购它们
COALESCE
似乎不是最适合此排序的函数,因为它只是 returns 第一个非 NULL
值,这在进行比较时不直观操作数可以是 NULL
.
建议使用 CASE
而不是级别的虚拟整数值 - 如下所示:
ORDER BY CASE WHEN price_new IS NOT NULL AND price_new <> price THEN 1
WHEN price_new IS NULL THEN 2
WHEN price IS NULL THEN 3
ELSE 4
END
查看此 SQLFiddle 演示:http://sqlfiddle.com/#!9/57c8eb3/6。
您可以使用 IFNULL、CASE WHEN 和 UNION 编写更好的解决方案。
解决方案 - http://sqlfiddle.com/#!9/57c8eb3/21
SELECT fn.name AS name_new, fo.date_updated, fo.id, fo.name,fo.price,
fo.product_code, fn.product_code AS product_code_new, fo.stock, fn.price AS price_new,
fn.stock AS stock_new, fn.date_updated AS date_updated_new,
(case when (IFNULL(fn.product_code,'X') != 'X' and fo.price != fn.price)
then 'Level1'
when IFNULL(fn.product_code,'X') = 'X' then 'Level2'
else 'Level4' end) as Ordering_level
FROM feed_old fo LEFT JOIN feed_new fn
ON fo.product_code = fn.product_code
UNION
SELECT fn.name AS name_new, fo.date_updated, fo.id, fo.name,fo.price,
fo.product_code, fn.product_code AS product_code_new, fo.stock,
fn.price AS price_new, fn.stock AS stock_new, fn.date_updated AS date_updated_new,
(case when (IFNULL(fo.product_code,'X') != 'X' and fo.price != fn.price)
then 'Level1'
when IFNULL(fo.product_code,'X') = 'X' then 'Level3'
else 'Level4' end) as Ordering_level
FROM feed_old fo RIGHT JOIN feed_new fn
ON fn.product_code = fo.product_code
order by ordering_level
我有两个 tables feed_old(默认数据)和 feed_new(新数据),其中 cron 作业将每天 运行 并且仅更新 feed_new table 与当前信息
Cron 作业
$url = "localhost/test.xml";
$xml = simplexml_load_file($url);
$this->db->query("TRUNCATE TABLE feed_new");
$date = date('Y-m-d H:i:s');
foreach($xml->Product as $item)
{
$data = array(
'product_code' => $item->ProductCode,
'name' => $item->Name,
'price' => $item->RetailCurrentPrice,
'stock' => (int)$item->Stock,
'manufacture' => '1',
'date_updated' => $date
);
$update_status = $this->model_price->check_price($data);
}
型号
public function check_price($data)
{
if($data) {
$insert = $this->db->insert('feed_new', $data);
return ($insert == true) ? true : false;
}
}
自此一切正常
当我比较 feed_new 与 feed_old 并获取所有更改并显示所有记录时,问题就来了
比较 feed_new 与 feed_old 之后,我想从 table 中提取所有记录并按级别排序
级别 1 - 如果产品有不同的价格 feed_new.price <> feed_old.price
2 级 - 如果来自 feed_old 的产品在 feed_new 中不存在(这意味着产品不再受支持)
3 级 - 如果来自 feed_new 的产品在 feed_old 中不存在(这意味着产品是新的)
4 级 - 其余结果
比较查询
SELECT fn.name AS name_new, fo.date_updated, fo.id, fo.name,fo.price,fo.product_code, fn.product_code AS product_code_new, fo.stock, fn.price AS price_new, fn.stock AS stock_new, fn.date_updated AS date_updated_new
FROM feed_old fo
LEFT JOIN feed_new fn ON fo.product_code = fn.product_code
UNION ALL
SELECT fn.name AS name_new, fo.date_updated, fo.id, fo.name,fo.price,fo.product_code, fn.product_code AS product_code_new, fo.stock, fn.price AS price_new, fn.stock AS stock_new, fn.date_updated AS date_updated_new
FROM feed_old fo
RIGHT JOIN feed_new fn ON fn.product_code = fo.product_code
WHERE fo.product_code IS NULL OR fn.name IS NULL ORDER BY COALESCE(price <> price_new, name_new is NULL, product_code IS NULL) DESC
问题是级别 - 3 总是显示在最后一条记录中,我的意思是在级别 - 4 之后 在我下面的工作示例中,您可以看到 name_new -> test3 位于 table 的底部,而此时应该位于第 3 个位置
如何按以上级别订购它们
COALESCE
似乎不是最适合此排序的函数,因为它只是 returns 第一个非 NULL
值,这在进行比较时不直观操作数可以是 NULL
.
建议使用 CASE
而不是级别的虚拟整数值 - 如下所示:
ORDER BY CASE WHEN price_new IS NOT NULL AND price_new <> price THEN 1
WHEN price_new IS NULL THEN 2
WHEN price IS NULL THEN 3
ELSE 4
END
查看此 SQLFiddle 演示:http://sqlfiddle.com/#!9/57c8eb3/6。
您可以使用 IFNULL、CASE WHEN 和 UNION 编写更好的解决方案。
解决方案 - http://sqlfiddle.com/#!9/57c8eb3/21
SELECT fn.name AS name_new, fo.date_updated, fo.id, fo.name,fo.price,
fo.product_code, fn.product_code AS product_code_new, fo.stock, fn.price AS price_new,
fn.stock AS stock_new, fn.date_updated AS date_updated_new,
(case when (IFNULL(fn.product_code,'X') != 'X' and fo.price != fn.price)
then 'Level1'
when IFNULL(fn.product_code,'X') = 'X' then 'Level2'
else 'Level4' end) as Ordering_level
FROM feed_old fo LEFT JOIN feed_new fn
ON fo.product_code = fn.product_code
UNION
SELECT fn.name AS name_new, fo.date_updated, fo.id, fo.name,fo.price,
fo.product_code, fn.product_code AS product_code_new, fo.stock,
fn.price AS price_new, fn.stock AS stock_new, fn.date_updated AS date_updated_new,
(case when (IFNULL(fo.product_code,'X') != 'X' and fo.price != fn.price)
then 'Level1'
when IFNULL(fo.product_code,'X') = 'X' then 'Level3'
else 'Level4' end) as Ordering_level
FROM feed_old fo RIGHT JOIN feed_new fn
ON fn.product_code = fo.product_code
order by ordering_level