表变量:有更清洁的方法吗?

时间:2009-11-10 01:41:00

标签: sql

我有一张桌子,用于存储我为之工作的各种客户,由政府和商业专栏分隔。问题是任一列中的客户端数量可能不均匀。当我做一个SELECT时,我在不规则的地方最终得到NULL值,因为我想不出一个简单的方法来订购结果集。例如,使用直接SELECT(无ORDER BY)可以实现以下功能:

Government | Commercial
DOD        | IBM
DOS        | Microsoft
           | Novell
DVA        | Oracle

如您所见,政府专栏中有一个NULL值,因为商业客户比政府多。这可能随时发生变化,并且无法保证哪个列具有更多值。为了消除结果集中间空白值的渲染,我决定对表变量执行两个单独的SELECT(一个用于政府客户端,另一个用于商业用户),然后SELECT最后一次,将它们连接在一起:< / p>

DECLARE @Government TABLE
(
    Row int,
    PortfolioHistoryId uniqueidentifier,
    Government varchar(40),
    GovernmentPortfolioContentId uniqueidentifier
)

DECLARE @Commercial TABLE
(
    Row int,
    PortfolioHistoryId uniqueidentifier,
    Commercial varchar(40),
    CommercialPortfolioContentId uniqueidentifier
)

INSERT INTO @Government
    SELECT
        (ROW_NUMBER() OVER (ORDER BY Government)) AS Row,
        PortfolioHistoryId,
        Government,
        GovernmentPortfolioContentId
    FROM dbo.PortfolioHistory
    WHERE Government IS NOT NULL

INSERT INTO @Commercial
    SELECT
        (ROW_NUMBER() OVER (ORDER BY Commercial)) AS Row,
        PortfolioHistoryId,
        Commercial,
        CommercialPortfolioContentId
    FROM dbo.PortfolioHistory
    WHERE Commercial IS NOT NULL

SELECT
    g.Government,
    c.Commercial,
    g.GovernmentPortfolioContentId,
    c.CommercialPortfolioContentId
FROM @Government AS g
FULL OUTER JOIN @Commercial AS c ON c.Row = g.Row

我不一定对这个查询不满意(也许我应该这样),但是有更清晰的方法来实现它吗?

4 个答案:

答案 0 :(得分:1)

您必须具有将管理表连接到商用表的governID。在商业表格中插入值时,您还必须在您希望商业行所在的位置插入一个governID。

Government           Commercial
governID     |    NAME       commID     | com_govID   | Name
   1             BIR            1             1          Netopia
                                2             1          SM Mall

所以如果你查询它。

SELECT
    g.Government,
    c.Commercial,
    g.GovernmentPortfolioContentId,
    c.CommercialPortfolioContentId
FROM @Government AS g
FULL INNER JOIN @Commercial AS c ON c.governID = com_govID

答案 1 :(得分:1)

从设计的角度来看,我不明白为什么你需要两个表,甚至两列政府/商业。您可以让表Clients包含OrganizationType的分类符列。例如:

DECLARE TABLE Customer (
 ID int
 ,Name varchar(50)
 ,OrganizationType char(1)
 ,Phone varchar(12)
 )

对于OrganizationType,您可以使用:G = gov,B =商业/商业,C =慈善机构。查询表时,在ORDER BY和GROUP BY中使用OrganizationType
如果gov和business客户端有一些特定的列,那么将所有公共列保留在Customer表中,并将特定列移动到单独的子类型GovernmentCommercial表中与 this example 中一样。在这个例子中,书籍和杂志是出版物的类型 - 在你的例子中,政府和商业是客户的类型。

答案 2 :(得分:1)

SELECT
  Government,
  Commercial,
  GovernmentPortfolioContentId,
  CommercialPortfolioContentId
FROM dbo.PortfolioHistory
ORDER BY
  CASE WHEN Government is null THEN 2 ELSE 1 END,
  CASE WHEN Commercial is null THEN 2 ELSE 1 END,
  Government,
  Commercial

除此之外:在变量表中,“Row”列应声明为PRIMARY KEY - 以获得聚簇索引的优势。

答案 3 :(得分:0)

一般来说,渲染问题应该在应用层中处理。做一个直接的SELECT,然后将其处理成你想要的格式。

所以:

SELECT DISTINCT client, client_type FROM clients table;

然后在你的应用程序层(我将使用快速和脏的PHP):

foreach($row = $result->fetch_assoc()) {
  if($row['client_type']=='gov') {
     $gov[]=$row['client'];
  } else {
    $com[]=$row['client']; 
  }
}

$limit=(count($gov)>$count($com)) ? count($gov) : count($com);

echo '<table><tr><th>Gov</th><th>Com</th><tr>';
for($i=0; $i< $limit; $i++) {
   echo "<tr><td>{$gov[$i]}</td><td>{$com[$i]}</td></tr>\n";
}
echo '</table>