从复杂的SQL表中获取数据

从复杂的SQL表中获取数据,sql,oracle,Sql,Oracle,我在下面提到了Oracle中的SQL表 FILE_NAME) ROW_NUMBER COL_NAME COL_VALUE ----------------------------------------- -------------------- ------------- EnivData.properties 1 Host server1.com EnivData.pr

我在下面提到了Oracle中的SQL表

FILE_NAME)            ROW_NUMBER     COL_NAME      COL_VALUE  
----------------------------------------- -------------------- -------------
EnivData.properties    1            Host                 server1.com          
EnivData.properties    1            Port                 8081                 
EnivData.properties    1            Username             server1user          
EnivData.properties    2            Host                 win-serv2.com        
EnivData.properties    2            Port                 9900                 
EnivData.properties    2            Username             server2-user-john    
EnivData.properties    3            Host                 linux-server3.com    
EnivData.properties    3            Port                 7898                 
EnivData.properties    3            Username             server3-user-mike    
下面提到的查询工作正常

select col_value 
from testmytable  
where col_name='Port' and 
      row_number = (select row_number 
                    from TESTMYTABLE  
                    where col_name='Host' and Col_Value='server1.com')
现在,我需要为
Username
获取
COL\u值的值,其中
Host=server1.com和Port=8081

我无法在SQL查询中放入正确的where子句,该子句可以为我提供正确的结果(
COL\u VALUE
for
Username


请提供帮助。

您可以使用以下查询获取输出。但是,如果您确定每行号总是有3个条目,那么可能会有比这更好的解决方案

select * 
  from (
select col_name,col_value 
  from testmytable 
 where  row_number in (select row_number 
                         from TESTMYTABLE  
                        where col_name='Host' 
                         and Col_Value='server1.com')
   and row_number in (select row_number 
                         from TESTMYTABLE  
                        where col_name='Port' 
                         and Col_Value='8081')
        )x
   where x.col_name in('Host','Port','Username')
另一种解决方案是将行转换为列(即具有列host_val、port_val、username_val),并根据您希望搜索的值筛选列

例如:


您可以使用以下查询来获取输出。但是,如果您确定每行号总是有3个条目,那么可能会有比这更好的解决方案

select * 
  from (
select col_name,col_value 
  from testmytable 
 where  row_number in (select row_number 
                         from TESTMYTABLE  
                        where col_name='Host' 
                         and Col_Value='server1.com')
   and row_number in (select row_number 
                         from TESTMYTABLE  
                        where col_name='Port' 
                         and Col_Value='8081')
        )x
   where x.col_name in('Host','Port','Username')
另一种解决方案是将行转换为列(即具有列host_val、port_val、username_val),并根据您希望搜索的值筛选列

例如:


键/值表最好通过聚合进行访问。以下是如何查找主机
'server1.com'
和端口
'8081'
的用户名

select max(case when col_name = 'Username' then col_value end)
from testmytable  
group by row_number
having max(case when col_name = 'Host' then col_value end) = 'server1.com'
   and max(case when col_name = 'Port' then col_value end) = '8081';

键/值表最好通过聚合进行访问。以下是如何查找主机
'server1.com'
和端口
'8081'
的用户名

select max(case when col_name = 'Username' then col_value end)
from testmytable  
group by row_number
having max(case when col_name = 'Host' then col_value end) = 'server1.com'
   and max(case when col_name = 'Port' then col_value end) = '8081';

您可以
JOIN
将表与其自身连接起来,以将相关数据拉到一起:

SELECT
    t1.COL_VALUE AS 'Host',
    t2.COL_VALUE AS 'Port',
    t3.COL_VALUE AS 'User'
FROM       t AS t1
INNER JOIN t AS t2 ON t1.ROW_NUMBER = t2.ROW_NUMBER AND t2.COL_NAME = 'Port'
INNER JOIN t AS t3 ON t1.ROW_NUMBER = t3.ROW_NUMBER AND t3.COL_NAME = 'Username'
WHERE t1.COL_NAME = 'Host' -- this is important
-- you now have the three values available inside t1.COL_VALUE, t2.COL_VALUE
-- and t3.COL_VALUE waiting to be filtered
AND   t1.COL_VALUE = 'server1.com'
AND   t2.COL_VALUE = '8081'
或者,您可以使用
EXISTS

SELECT col_value
FROM t
WHERE col_name = 'username'
AND EXISTS (
    SELECT 1
    FROM t
    WHERE row_number = t.ROW_NUMBER AND col_name = 'host' AND col_value = 'server1.com'
)
AND EXISTS (
    SELECT 1
    FROM t
    WHERE row_number = t.ROW_NUMBER AND col_name = 'port' AND col_value = '8081'
)

您可以
JOIN
将表与其自身连接起来,以将相关数据拉到一起:

SELECT
    t1.COL_VALUE AS 'Host',
    t2.COL_VALUE AS 'Port',
    t3.COL_VALUE AS 'User'
FROM       t AS t1
INNER JOIN t AS t2 ON t1.ROW_NUMBER = t2.ROW_NUMBER AND t2.COL_NAME = 'Port'
INNER JOIN t AS t3 ON t1.ROW_NUMBER = t3.ROW_NUMBER AND t3.COL_NAME = 'Username'
WHERE t1.COL_NAME = 'Host' -- this is important
-- you now have the three values available inside t1.COL_VALUE, t2.COL_VALUE
-- and t3.COL_VALUE waiting to be filtered
AND   t1.COL_VALUE = 'server1.com'
AND   t2.COL_VALUE = '8081'
或者,您可以使用
EXISTS

SELECT col_value
FROM t
WHERE col_name = 'username'
AND EXISTS (
    SELECT 1
    FROM t
    WHERE row_number = t.ROW_NUMBER AND col_name = 'host' AND col_value = 'server1.com'
)
AND EXISTS (
    SELECT 1
    FROM t
    WHERE row_number = t.ROW_NUMBER AND col_name = 'port' AND col_value = '8081'
)


您还可以发布希望在查询输出中看到的确切记录吗?确切记录是-Username=server1user。我需要从上面提到的表中获取“server1user”,其中Host=“server1.com”和Port=8081。希望,我已经回答了您的问题。使用键/值表不是很麻烦吗?;-)有没有一个很好的理由不让一个表包含主机、端口和用户名三列?“那会好得多!”托尔斯滕克特纳说,“如果还有十几种其他设置呢?”?那么桌子就会水平地生长。@Salman A:是的。怎么了?我见过有超过100个属性的表。在Abhay Agarwal的表中,所有三个属性都是强制性的,因此,最好有一个适当的表,其中包含三个不可为空的列,这些列具有适当的数据类型,并且具有适当的唯一键,而不是键/值表。您还可以发布希望在查询输出中看到的确切记录吗?确切记录为-Username=server1user。我需要从上面提到的表中获取“server1user”,其中Host=“server1.com”和Port=8081。希望,我已经回答了您的问题。使用键/值表不是很麻烦吗?;-)有没有一个很好的理由不让一个表包含主机、端口和用户名三列?“那会好得多!”托尔斯滕克特纳说,“如果还有十几种其他设置呢?”?那么桌子就会水平地生长。@Salman A:是的。怎么了?我见过有超过100个属性的表。在Abhay Agarwal的表中,所有三个属性似乎都是必需的,因此最好有一个适当的表,其中包含三个不可为空的列,具有适当的数据类型,并具有适当的唯一键,而不是键/值表。是的,我确信每行将有确切的3个条目感谢您的回复。请让我知道,如果我们每行有3个条目,是否有更好的解决方案。一个选项是将行转换为列(即将列作为host\u val、port\u val和username\u val),然后过滤掉它们。我已经包括了另一个解决方案是的,我确信每行有3个条目。谢谢你的回复。请让我知道,如果我们每行有3个条目,是否有更好的解决方案。一个选项是将行转换为列(即将列作为host\u val、port\u val和username\u val),然后过滤掉它们。我已经包括了另一个解决方案谢谢你的回复。我需要两者的结合-意思是主机=server1.com和端口=8081,那么“用户名”的值是多少。我在我的答案中添加了一个典型的键/值查询,应该可以得到你想要的结果。我删除了我的原始答案。乔治·约瑟夫(George Joseph)刚刚更新了他的答案,以显示与我类似的问题。您可能更喜欢他的解决方案,因为他的
WITH
子句使查询更具可读性。无论如何,您似乎应该更改表设计,以便首先拥有一个包含主机、端口和用户名三列的适当表。是的,键值数据库设计在获取数据时存在问题,很容易将数据插入一个大表中,但很难编写查询。还担心数据完整性(要强制执行的约束将非常困难。例如:强制执行端口号应该是唯一的、外键不可能、日期验证等),感谢您的回复。我需要两者的结合-意思是主机=server1.com和端口=8081,那么“用户名”的值是多少。我在我的答案中添加了一个典型的键/值查询,应该可以得到你想要的结果。我删除了我的原始答案。乔治·约瑟夫(George Joseph)刚刚更新了他的答案,以显示与我类似的问题。您可能更喜欢他的解决方案,因为他的
WITH
子句使查询更具可读性。无论如何,您似乎应该更改表设计,以便首先拥有一个包含主机、端口和用户名三列的适当表。是的,键值数据库设计在获取数据时存在问题,很容易将数据插入一个大表中,但很难编写查询。还担心数据完整性(要强制执行的约束将非常困难。例如:强制执行端口号应该是唯一的、外键不可能、日期限制)