【问题标题】:Multiple column values in where clausewhere 子句中的多个列值
【发布时间】:2015-06-30 06:24:37
【问题描述】:

我需要像时间表一样显示每周的单用户时间表,

场景:一个教师在同一天分配到多个批次(例如:BBA,数学和上午 1 和 2 小时)和(MBA,数学,下午 3 和 4 小时),例如(30-06 -2015)。我的gridview 行将存储为1 和2 行存储为2 等等............

我的表定义:

CREATE TABLE [dbo].[test] (
    [datedif]     NVARCHAR (50)  NOT NULL,
    [hour]         INT              NULL,
    [subject]    NVARCHAR (MAX) NULL,
    [faculty]    NVARCHAR (MAX) NULL,
    [attendence] BIT            NULL,
    [dayweek]     NVARCHAR (50)  NULL,
    [weekmonth]   NVARCHAR (MAX) NULL,
    [batch]       NVARCHAR (MAX) NULL,
    [section]     NVARCHAR (MAX) NULL,
    [session]     NVARCHAR (MAX) NULL
);

表格看起来像:

Datefdiff | hour | subject | faulty| batch
----------+-------+----------+---------+-------+----------+--------+-------+----------+---------+-------
30-06-2015| 1| Maths    | Kevin   | BBA
30-06-2015| 2| Science  | Amal    | MBA
30-06-2015|3 | chemistry|Jaya     |BBA
30-06-2015|4 | chemistry|Jaya     |BBA 
30-06-2015|5 | chemistry|Jaya     |BBA
31-06-2015 |1| science  | Amal    |BBA
31-06-2015 |2| Maths    | kevin   |BBA 
31-06-2015 |3| Science  | Amal    |BBA 
31-06-2015 |4 | chemistry|Jaya     |BBA
31-06-2015 |5| science  | Amal    |BBA

预计只为教员提供输出:Amal

Datefdiff |hour|subject| batch |hour|subject | batch |faculty|hour | subject | batch | hour | subject | batch| hour | subject | batch | 
----------+-------+----------+-------+-------+----------+-------+-------+----------+
30-06-2015| 1    | Maths| BBA| 2| Science  | MBA   | 3| Science  |   BBA| 4| chemistry| BBA | 5 |Physics |MBA
31-06-2015| 1    | Maths| BBA| 2| Science  | MBA   | 3| Science  |   BBA| 4| chemistry| BBA | 5 |Physics |MBA

【问题讨论】:

  • 那是一个糟糕的桌子设计。您不应该存储数据来模仿某些显示/表单。数据应该是不可透视的,以便所有例如subject 数据最终出现在 same 列中。然后添加一个可以存储数字 1-5 的额外列,并为该列指定一个 name,以解释该数据代表什么(您当前嵌入到表 元数据中的数据i> 错误)
  • 感谢您的建议,但如果我可以通过在 where 子句中使用它来显示教员日程的详细信息,那将很有帮助,同时我将尝试将表定义更改为你建议的。
  • 在更改表定义时,请记住日期值应存储在日期数据类型中,而 nvarchar(max) 用于极长的 unicode 字符串。由于您的字符串似乎既简短又简单,您可以使用 varchar(50) 或任何其他适合您需要的长度。另外,我建议对您的数据进行规范化 - 有一个主题表、一个批处理表、一个故障表等等。
  • Nvarchar(max) - 坏主意!!!
  • 您的表格未标准化。修复您的数据库设计。

标签: c# sql sql-server tsql


【解决方案1】:

这可能是您的表格设计的起点:

declare @tbFaculty table (
      FacultyID int --identity(1,1) primary key
    , Name varchar(50)
)

insert into @tbFaculty ( FacultyID, Name )
values    ( 1, 'Kevin' )
        , ( 2, 'Amal' )

declare @tbBatch table(
      BatchID int --identity(1,1) primary key
    , Name char(3)
)

insert into @tbBatch ( BatchID, Name )
values    ( 1, 'BBA' )
        , ( 2, 'MBA' )

declare @tbClass table (
      [Hour] tinyint
    , [Subject] nvarchar (128)
    , [FacultyID] int
    , [Attendence] bit
    , [BatchID] char(3)
    , [ClassDate] date
)

insert into @tbClass ( [Hour], [Subject], FacultyID, Attendence, BatchID, ClassDate )
values    ( 1, 'Maths', 1, 1, 1, '2015-06-30' )
        , ( 2, 'Maths', 1, 1, 1, '2015-06-30' )
        , ( 3, 'Science', 2, 1, 1, '2015-06-30' )
        , ( 1, 'Science', 2, 1, 2, '2015-06-30' )
        , ( 2, 'Science', 2, 1, 2, '2015-06-30' )
        , ( 3, 'Maths', 1, 1, 2, '2015-06-30' )

select
    cl.ClassDate
    , cl.[Hour]
    , cl.[Subject]
    , ba.Name as BatchName
    , fa.Name as FacultyName
from
    @tbClass cl
    inner join @tbBatch ba on ba.BatchID = cl.BatchID
    inner join @tbFaculty fa on fa.FacultyID = cl.FacultyID
where
    fa.Name = 'Amal'

您也可以规范化主题。

【讨论】:

    【解决方案2】:

    我只是将其添加为单独的答案。试试这个:

    --INSERT INTO dbo.test(datedif,[hour],[subject],faculty,batch)
    --VALUES
    --('30-06-2015',1,'Maths','Kevin','BBA'),
    --('30-06-2015',2,'Science','Amal','MBA'),
    --('30-06-2015',3,'chemistry','Jaya','BBA'),
    --('30-06-2015',4,'chemistry','Jaya','BBA'),
    --('30-06-2015',5,'chemistry','Jaya','BBA'),
    --('31-06-2015',1,'science','Amal','BBA'),
    --('31-06-2015',2,'Maths','kevin','BBA'),
    --('31-06-2015',3,'Science','Amal','BBA'),
    --('31-06-2015',4,'chemistry','Jaya','BBA'),
    --('31-06-2015',5,'science','Amal','BBA');
    
    WITH CTE_Hours
    AS
    (
        SELECT
                1 AS hour1,
                MAX(CASE WHEN [Hour] = 1 THEN [subject] END)    AS subject1,
                MAX(CASE WHEN [Hour] = 1 THEN [batch] END)      AS batch1 ,
    
                2 AS hour2,
                MAX(CASE WHEN [Hour] = 2 THEN [subject] END)    AS subject2,
                MAX(CASE WHEN [Hour] = 2 THEN [batch] END)      AS batch2
    
                --etc...
        FROM dbo.test
        WHERE faculty = 'Amal'
    )
    
    SELECT *
    FROM    (
                SELECT DISTINCT datedif
                FROM dbo.test
            ) A
    CROSS JOIN CTE_Hours
    

    【讨论】:

      【解决方案3】:

      以下是标准化数据的方法,这将使查询变得更加简单。

      使用您的表定义,我插入了您的数据

      INSERT INTO test(Datedif,hour1,subject1,faculty1,hour2,subject2,faculty2,hour3,subject3,faculty3,batch)
      VALUES  ('30-06-2015',1,'Maths','Kevin',1,'Maths','Kevin',1,'Science','Amal','BBA'),
              ('30-06-2015',1,'Science','Amal',1,'Science','Amal',1,'Maths','Kevin','MBA');
      

      然后,我为您的数据创建了一个新的规范化结构,具有更窄的数据类型。它有助于保持数据清洁以及不浪费存储空间,这意味着查询会更快,因为它们不必处理太多数据。

      CREATE TABLE new_test
      (
          dt          DATE            NULL,
          hr          TINYINT         NULL, --holds values between 0 to 255
          subj        VARCHAR(100)    NULL, --plenty big enough. No need for NVARCHAR unless you are using Unicode characters
          faculty     VARCHAR(100)    NULL,
          attendance  BIT             NULL,
          dayweek     TINYINT         NULL,
          weekmonth   TINYINT         NULL,
          section     VARCHAR(100)    NULL, --not sure what this is
          sess        VARCHAR(100)    NULL, --not sure what this is
          batch       CHAR(3)         NULL  --looks like there are three character codes
      );
      

      这是我标准化您的数据的地方。我不确定你是否有出席 2、3、4 等...如果你在实际表中这样做,那么你应该修复我的代码。

      注意:我从日期开始计算 dayweek 和 weekmonth。我已经尽力猜测了,如果它们不正确,请随时调整它们!

      WITH norm_data
      AS
      (
      SELECT datedif,hour1,subject1,faculty1,attendence1,dayweek,weekmonth,section,[session],batch FROM test
      UNION ALL
      SELECT datedif,hour2,subject2,faculty2,attendence1,dayweek,weekmonth,section,[session],batch FROM test
      UNION ALL
      SELECT datedif,hour3,subject3,faculty3,attendence1,dayweek,weekmonth,section,[session],batch FROM test
      UNION ALL
      SELECT datedif,hour4,subject4,faculty4,attendence1,dayweek,weekmonth,section,[session],batch FROM test
      UNION ALL
      SELECT datedif,hour5,subject5,faculty5,attendence1,dayweek,weekmonth,section,[session],batch FROM test
      )
      
      INSERT INTO new_test
      SELECT  PARSE(datedif AS DATE USING 'de-DE') AS [datedif],
              hour1,
              subject1,
              faculty1,
              attendence1,
              DATEPART(WEEKDAY,PARSE(datedif AS DATE USING 'de-DE')) AS dayweek,
              datepart(day, datediff(day, 0, PARSE(datedif AS DATE USING 'de-DE'))/7 * 7)/7 + 1 AS weekmonth,
              section,
              [session],
              batch
      FROM norm_data
      

      现在让我们看看你的新表

      SELECT *
      FROM new_test
      

      如果正确,那么这里是重命名表的方法

      EXEC SP_rename  @objname = 'test', --if you don't want to drop the old table
                      @newname = 'test_old'
      
      EXEC SP_rename  @objname = 'new_test', --now give the new table the actual name
                      @newname = 'test'
      
      
      SELECT *
      FROM test
      

      【讨论】:

      • 我已根据您的建议更改了我的表格。您可以在上面看到我更改的表格。我如何加入它们并在网格视图中显示。请给我一些想法。请明智地查看上面的网格视图我应该得到输出
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-11
      • 2015-08-17
      • 2021-12-05
      • 2014-02-16
      相关资源
      最近更新 更多