仅在满足某些条件的情况下才尝试投射列

时间:2018-06-26 16:36:55

标签: sql sql-server

我的公司使用媒体管理软件,该软件将媒体的所有元数据存储在1个表格中(尺寸,标题,标题,标签等)。因此,所有值的类型均为Starting inspector on 127.0.0.1:9229 failed: address already in use。这不是一个大问题,因为每一行都有一个名为VARCHAR的字段,该字段定义该行中存在的数据类型。例如,MetaName 1是标题字段,MetaName 3是高度(以像素为单位)。

我正在尝试查找某些尺寸(以像素为单位)之间的图像。由于这些值存储为MetaName类型,例如VARCHAR,因此在测试像这样的大小范围之前,我需要替换1200px并强制转换为px:{{ 1}}。

这是一个简化的架构和一个示例,可以更容易地理解我在说什么:

INT

测试值和我的查询:

CAST(REPLACE(VALUE, 'px', '') AS INT)

这应该可以正常工作,但是CREATE TABLE Media ( ID INT IDENTITY(1,1) PRIMARY KEY, ImagePath VARCHAR(MAX) ); CREATE TABLE MetaData ( ID INT IDENTITY(1,1) PRIMARY KEY, MediaId INT REFERENCES Media(ID), MetaName INT NOT NULL, Value VARCHAR(MAX) NOT NULL DEFAULT '' ); 调用失败,因为查询尝试转换所有Value列,因此当它运行到“ Title1”或“ Description1”时,会发生错误。

如何仅对MetaName = 3或4的字段进行强制转换?我认为INSERT INTO Media (ImagePath) VALUES ('C:/mypath/myimage.png'), ('C:/mypath/otherimage.jpg'); INSERT INTO MetaData (MediaId, MetaName, Value) VALUES (1, 1, 'Title1'), (2, 1, 'Title2'), (1, 2, 'Description1'), (2, 2, 'Description2'), (1, 3, '1260px'), (2, 3, '1100px'), (1, 4, '800px'), (2, 4, '1900px'); SELECT * FROM MetaData WHERE (MetaName = 3 AND CAST(REPLACE(Value, 'px', '') AS INT) BETWEEN 800 AND 1200) OR (MetaName = 4 AND CAST(REPLACE(Value, 'px', '') AS INT) BETWEEN 800 AND 1200) CAST位于条件语句开头,而MetaName = 3会阻止MetaName = 4 + AND执行,但所有情况都会发生列。

3 个答案:

答案 0 :(得分:3)

您可以在SQL Server 2012及更高版本上使用try_convert

SELECT * FROM MetaData
WHERE 
 (MetaName = 3 AND try_convert(int,REPLACE(Value, 'px', '')) BETWEEN 800 AND 1200)
 OR
 (MetaName = 4 AND try_convert(int,REPLACE(Value, 'px', '')) BETWEEN 800 AND 1200)

或try_cast

SELECT * FROM MetaData
WHERE 
 (MetaName = 3 AND try_cast(REPLACE(Value, 'px', '') as int) BETWEEN 800 AND 1200)
 OR
 (MetaName = 4 AND try_cast(REPLACE(Value, 'px', '') as int) BETWEEN 800 AND 1200)

或者,您可以将演员表换成CASE

SELECT * FROM MetaData
where
(MetaName = 3 AND case when MetaName = 3 then CAST(REPLACE(Value, 'px', '') AS INT) end BETWEEN 800 AND 1200)
 OR
(MetaName = 4 AND case when MetaName = 4 then CAST(REPLACE(Value, 'px', '') AS INT) end BETWEEN 800 AND 1200)

或者,使用IIF

SELECT * FROM MetaData
where
(MetaName = 3 AND iif(MetaName = 3,CAST(REPLACE(Value, 'px', '') AS INT),null) BETWEEN 800 AND 1200)
 OR
(MetaName = 4 AND iif(MetaName = 4,CAST(REPLACE(Value, 'px', '') AS INT),null) BETWEEN 800 AND 1200)

或者,使用CTE分解过滤条件。

;with cte as(
SELECT * FROM MetaData
where MetaName in (3,4))

select *
from cte
where CAST(REPLACE(Value, 'px', '') AS INT) BETWEEN 800 AND 1200

答案 1 :(得分:2)

 SELECT * FROM MetaData
 WHERE 
 ( case when (MetaName = 3 or MetaName = 4)  then  CAST(REPLACE(Value, 'px', '') AS INT) else NULL end )  
  BETWEEN 800 AND 1200

答案 2 :(得分:2)

您可以使用TRY_CAST代替CAST。

SELECT * FROM MetaData
WHERE 
 (MetaName = 3 AND TRY_CAST(REPLACE(Value, 'px', '') AS INT) BETWEEN 800 AND 1200)
 OR
 (MetaName = 4 AND TRY_CAST(REPLACE(Value, 'px', '') AS INT) BETWEEN 800 AND 1200)

当我这样做时,它仅返回MetaNames 3和4作为结果集的一部分。我相信此功能是在SQL Server 2012中引入的。