Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
仅当存在非空值时,SQL左连接非空值_Sql_Subquery_Left Join - Fatal编程技术网

仅当存在非空值时,SQL左连接非空值

仅当存在非空值时,SQL左连接非空值,sql,subquery,left-join,Sql,Subquery,Left Join,我正在使用地理位置变量,我相信这应该比我现在做的简单得多 我想返回一行,并将其他三个“选项”作为其他值左键连接到该行,这是通过使用用户的地理位置来完成的,一些选项将根据这一点而有所不同。所有选项都有一个默认值,因此我只想在匹配地理位置时覆盖默认值 表1将有汉堡、热狗等项目,而表2将有点像浇头,每个项目将有多达三层浇头,一些将根据地理位置进行更改 表一 |id | name | ______________ |0 | burger | |1 | hotdog |

我正在使用地理位置变量,我相信这应该比我现在做的简单得多

我想返回一行,并将其他三个“选项”作为其他值左键连接到该行,这是通过使用用户的地理位置来完成的,一些选项将根据这一点而有所不同。所有选项都有一个默认值,因此我只想在匹配地理位置时覆盖默认值

表1将有汉堡、热狗等项目,而表2将有点像浇头,每个项目将有多达三层浇头,一些将根据地理位置进行更改

表一

   |id | name   |
   ______________
   |0  | burger |
   |1  | hotdog |
表二

   |topid | topping | layer | location
   ___________________________________
   | 0    | catsup  | 1     | 
   | 1    | mustard | 2     | 
   | 2    | onion   | 3     | 
   | 3    | lettuce | 3     | US
   | 4    | bacon   | 3     | CA


$geo = 'CA';
mySql


我的结果是只返回一个汉堡包和番茄酱、芥末,在第3层的顶部有培根,因此我需要一个值,如果有空值和字母值,则以字母值为层,否则以空值为层。我希望在查询返回500多条记录的速度时不要使用嵌套选择,因为您的查询中存在一个问题,即
连接
条件的
ed部分应该在括号中,以获得您想要的结果,即条件应该如下所示:

ON layer1.layer = 1
AND (layer1.location IS NULL OR layer1.location = $geo)
修复后,查询将生成多行,具体取决于
two
中是否存在与
$geo
匹配的行。您可以根据每个层的位置是否为
NULL
,对这些行进行排序,从而使与大多数位置匹配的行成为第一行。然后可以使用
LIMIT 1
仅选择该行:

SELECT item.name, layer1.topping as `layer1`, layer2.topping as `layer2`, layer3.topping as `layer3` 
FROM `one` item
LEFT JOIN `two` layer1 
ON layer1.layer = 1
AND (layer1.location IS NULL OR layer1.location = '$geo')
LEFT JOIN `two` layer2 
ON layer2.layer = 2
AND (layer2.location IS NULL OR layer2.location = '$geo')
LEFT JOIN `two` layer3 
ON layer3.layer = 3
AND (layer3.location IS NULL OR layer3.location = '$geo')
WHERE item.id = 0
ORDER BY layer1.location IS NULL,
         layer2.location IS NULL,
         layer3.location IS NULL
LIMIT 1
输出(对于示例数据,假设
$geo='CA'
):

如果需要为所有
item.id
值获取该值,则需要使用嵌套的
SELECT
。这是一种方法:

SELECT item.name, layer1.topping as `layer1`, layer2.topping as `layer2`, layer3.topping as `layer3` 
FROM `one` item
LEFT JOIN `two` layer1 
ON layer1.layer = 1
AND (layer1.location IS NULL OR layer1.location = 'CA')
LEFT JOIN `two` layer2 
ON layer2.layer = 2
AND (layer2.location IS NULL OR layer2.location = 'CA')
LEFT JOIN `two` layer3 
ON layer3.layer = 3
AND (layer3.location IS NULL OR layer3.location = 'CA')
JOIN(
SELECT item.name,
       MIN((layer1.location IS NULL) + (layer2.location IS NULL) + (layer3.location IS NULL)) AS mostspecific
FROM `one` item
LEFT JOIN `two` layer1
ON layer1.layer = 1
AND (layer1.location IS NULL OR layer1.location = 'CA')
LEFT JOIN `two` layer2 
ON layer2.layer = 2
AND (layer2.location IS NULL OR layer2.location = 'CA')
LEFT JOIN `two` layer3 
ON layer3.layer = 3
AND (layer3.location IS NULL OR layer3.location = 'CA')
GROUP BY item.name
) sp ON item.name = sp.name AND (layer1.location IS NULL) + (layer2.location IS NULL) + (layer3.location IS NULL) = sp.mostspecific
输出:

name    layer1  layer2  layer3
burger  catsup  cheese  bacon
hotdog  catsup  cheese  bacon


注意,
$geo
应在引号中,否则将被视为列名。此外,正如Gordon在评论中指出的那样,表
two
似乎应该有一个
itemid
,这样您就可以将配料链接到特定的项目(以防您不希望培根成为热狗的有效配料)。

如果每个项目都有配料,然后,我希望在第二个表中有一个
itemid
。如果返回两个项目,那么order by在结束时会起作用,就像返回多行一样,因为limit 1将只返回一行。是否选择DISTICT work为多行返回第一个值?@RadiumChris如果您的意思是在
item.id上没有
WHERE
子句,则不会。你的问题中没有提到这个选项。。。您需要查询在该场景中工作吗?如果是这样,您将不得不使用嵌套选择。@RadiumChris您使用的是哪种SQL?MySQL,SQL server???什么版本?我运行的是MySQL5.7,我希望我缺少一些东西来进行快速修复,我可以使用嵌套选择器,或者只返回6个“toppings”(null和geo版本),如果在php中使用它们,则可以显示正确的值。在网络方面,速度推动了太多东西,我想我现在对很多东西都想得太多了。在5.7中没有。在8+中,您可以使用行号和CTE来轻松过滤。否则,您可以通过使用我的查询中显示的顺序,简单地获取每个项目遇到的第一行,在PHP中进行过滤。
SELECT item.name, layer1.topping as `layer1`, layer2.topping as `layer2`, layer3.topping as `layer3` 
FROM `one` item
LEFT JOIN `two` layer1 
ON layer1.layer = 1
AND (layer1.location IS NULL OR layer1.location = 'CA')
LEFT JOIN `two` layer2 
ON layer2.layer = 2
AND (layer2.location IS NULL OR layer2.location = 'CA')
LEFT JOIN `two` layer3 
ON layer3.layer = 3
AND (layer3.location IS NULL OR layer3.location = 'CA')
JOIN(
SELECT item.name,
       MIN((layer1.location IS NULL) + (layer2.location IS NULL) + (layer3.location IS NULL)) AS mostspecific
FROM `one` item
LEFT JOIN `two` layer1
ON layer1.layer = 1
AND (layer1.location IS NULL OR layer1.location = 'CA')
LEFT JOIN `two` layer2 
ON layer2.layer = 2
AND (layer2.location IS NULL OR layer2.location = 'CA')
LEFT JOIN `two` layer3 
ON layer3.layer = 3
AND (layer3.location IS NULL OR layer3.location = 'CA')
GROUP BY item.name
) sp ON item.name = sp.name AND (layer1.location IS NULL) + (layer2.location IS NULL) + (layer3.location IS NULL) = sp.mostspecific
name    layer1  layer2  layer3
burger  catsup  cheese  bacon
hotdog  catsup  cheese  bacon