Хранилище параметров SQL и справочник - PullRequest
1 голос
/ 06 января 2012

Если у меня есть таблица:

CREATE TABLE Kids (
    kid_id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    kid_name varchar(45) NOT NULL,
    kid_favcolors (text) NULL,
    PRIMARY_KEY(kid_id)
    )

и у меня есть таблица:

CREATE TABLE Colors (
    color_id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    color_name varchar(45) NOT NULL,
    PRIMARY_KEY(color_id)
)

Со строками, которые ссылаются на любимые цвета через идентификаторы, разделенные запятыми:

INSERT INTO Kids(kid_name, kid_favcolors) VALUES('Joe','1,2,3,4,5');
INSERT INTO Kids(kid_name, kid_favcolors) VALUES('Mary','1,2,3');

Как мне создать оператор, который бы возвращал каждую запись в базе данных Kid с именем Kid_name и color_name всех идентификаторов, на которые есть ссылки в столбце kid_favcolors.

Например:

COLORS:
color_id    color_name
1           yellow
2           green
3           blue
4           purple
5           red
6           brown
7           black
KIDS:
kid_id      kid_name    kid_favcolors
1           Joe         1,2,3,4,5
2           Mary        1,2,3

и я хочу получить

kid_id      kid_name    favorite_colors
1           Joe         yellow, green, blue, purple, red
2           Mary        yellow, green, blue

Запросы выполняются для существующих данных и структуры базы данных.Если выполнимого решения не существует, перестройка структуры данных возможна, но я предполагаю, что это добавит к решению значительное количество времени.В любом случае, мне нужна помощь.

Я могу получить цвета из базы данных, используя:

SELECT STUFF((SELECT ', ' + color_name FROM colors WHERE color_id IN (1,2,3,4,5) FOR XML PATH('')),1, 2, '') AS colors

        colors
1       yellow, green, blue, purple, red

Но когда я пытаюсь выполнить более сложный запрос, я не могу найтиспособ включить вышеупомянутое утверждение, извлекая идентификаторы из таблицы Kids.

SELECT kids.kid_id, kids.kid_name, favorite_colors FROM kids JOIN colors ON colors.id IN kids.kid_favcolors as favorite_colors

Хотя, похоже, это может работать для меня, а не работать.Не уверен, что я далеко или действительно близко.

Ответы [ 2 ]

0 голосов
/ 07 января 2012

Я разработал решение;хотя это не красиво, это работает.

SELECT 
  kid_id,
  kid_name, 
  (SELECT STUFF(
     (SELECT ', '+color_name FROM colors WHERE color_id in 
        (SELECT s from SplitString(kid_favcolors,',')) 
     FOR XML PATH(''))
   ,1,2,'')) AS favorite_colors 
FROM KIDS
kid_id      kid_name    favorite_colors
1           Joe         yellow, green, blue, purple, red
2           Mary        yellow, green, blue

Я говорил с ними о доработке БД и реализации текущего сайта администрирования, чтобы учесть изменения

Я использовал функцию Split String:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create function [dbo].[SplitString] 
(
    @str nvarchar(4000), 
    @separator char(1)
)
returns table
AS
return (
    with tokens(p, a, b) AS (
        select 
            1, 
            1, 
            charindex(@separator, @str)
        union all
        select
            p + 1, 
            b + 1, 
            charindex(@separator, @str, b + 1)
        from tokens
        where b > 0
    )
    select
        p-1 zeroBasedOccurance,
        substring(
            @str, 
            a, 
            case when b > 0 then b-a ELSE 4000 end) 
        AS s
    from tokens
  )
0 голосов
/ 06 января 2012

В исходном решении сохранение строки CSV в поле нарушает 1NF;фактически - по определению - таблица даже не квалифицируется как отношение.Таким образом, в этом случае обработайте строку как элементарный фрагмент данных и разложите ее на прикладном уровне.

Чтобы решить это на уровне БД, просто исправьте дизайн.

enter image description here

...