Question

hopefully this chart makes sense...

the problem is that I have many columns in the many-many table, how can I get all the column values in a view, without doing ISNULL for each row? (sql server 10.5)

 ITEM
+------+
| ID   |
|------|
| 1    |
| 2    |
| 3    |
+------+

 LANGUAGE
+-------+---------+
| ID    |  Name   |
|-------+---------|
| 1     | English |
| 2     | French  |
+-------+---------+

 Item Names
+----------+---------+------------+------------+
| ItemID   | LangId  |   Name     |   Color    |
|----------+---------+------------+------------|
| 1        |   1     |  apple     |  red       |
| 1        |   2     |  pomme     |  rouge     |
| 2        |   1     |  orange    |  orange    |
| 3        |   1     |  bannana   |  yellow    |
+----------+---------+------------+------------+

desired view

+----------+---------+------------+------------+
| ItemID   | LangId  |   Name     |   Color    |
|----------+---------+------------+------------|
| 1        |   1     |  apple     |  red       |
| 1        |   2     |  pomme     |  rouge     |
| 2        |   1     |  orange    |  orange    |
| 2        |   2     |  orange    |  orange    | <--- added automatically
| 3        |   1     |  bannana   |  yellow    |
| 3        |   2     |  bannana   |  yellow    | <--- added automatically
+----------+---------+------------+------------+

because I'm trying to create a view there are certain limitations:

The columns being modified in the view must directly reference the underlying data in the table columns. The columns cannot be derived in any other way, such as through the following:

  • An aggregate function: AVG, COUNT, SUM, MIN, MAX, GROUPING, STDEV, STDEVP, VAR, and VARP.
  • A computation. The column cannot be computed from an expression that uses other columns. Columns that are formed by using the set operators UNION, UNION ALL, CROSSJOIN, EXCEPT, and INTERSECT amount to a computation and are also not updatable.

I an however create multiple views, which is how I've gotten around some of these restrictions before. we can assume that I already have this table

intermediary view:

+----------+---------+------------+------------+
| ItemID   | LangId  |   Name     |   Color    |
|----------+---------+------------+------------|
| 1        |   1     |  apple     |  red       |
| 1        |   2     |  pomme     |  rouge     |
| 2        |   1     |  orange    |  orange    |
| 3        |   1     |  bannana   |  yellow    |
+----------+---------+------------+------------+

as well as:

+----------+---------+------------+------------+
| ItemID   | LangId  |   Name     |   Color    |
|----------+---------+------------+------------|
| 1        |   1     |  apple     |  red       |
| 1        |   2     |  pomme     |  rouge     |
| 2        |   1     |  orange    |  orange    |
| 2        |   2     |  -         |  -         |
| 3        |   1     |  bannana   |  yellow    |
| 3        |   2     |  -         |  -         |
+----------+---------+------------+------------+

these are some of the views:

view1 - all combinations

enter image description here

view2 - all combinations with languages enter image description here

the corresponding SQL:

SELECT     dbo.view1.ItemID, dbo.view1.LanguageID, dbo.ItemLanguages.Name, dbo.ItemLanguages.Color
FROM         dbo.ItemLanguages RIGHT OUTER JOIN
                      dbo.view1 ON dbo.ItemLanguages.LanguageID = dbo.view1.LanguageID AND dbo.ItemLanguages.ItemID = dbo.view1.ItemID

result of view 2 enter image description here

here is the test database with the views and tables: http://pastebin.com/4BpBSmHY

Was it helpful?

Solution

One way I've been able to do it is using ISNULL

SELECT     dbo.view1.ItemID,
    dbo.view1.LanguageID,
    ISNULL(dbo.ItemLanguages.Name,
      (SELECT     TOP (1) Name
        FROM          dbo.ItemLanguages AS x
        WHERE      (ItemID = dbo.view1.ItemID))) AS Name,
    ISNULL(dbo.ItemLanguages.Color,
      (SELECT     TOP (1) Color
        FROM          dbo.ItemLanguages AS x
        WHERE      (ItemID = dbo.view1.ItemID))) AS Color,
    CASE  
        WHEN  dbo.ItemLanguages.ItemID is NULL THEN 1
        ELSE 0
    END as valid

FROM         dbo.ItemLanguages RIGHT OUTER JOIN
                 dbo.view1 ON dbo.ItemLanguages.ItemID = dbo.view1.ItemID
                          AND dbo.ItemLanguages.LanguageID = dbo.view1.LanguageID

the reason why I don't like this approach is that I'm doing this across many more columns. I have the notion that doing multiple SELECTS would slow down the result drastically.

I though I'd be able to just check if the row exists like with the CASE
WHEN dbo.ItemLanguages.ItemID is NULL THEN 1 ELSE 0 END as valid
and then call the select once and populate all the columns

.. in a view

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top