【问题标题】:How can I use SqlDataReader to get grouped data returned by a stored procedure?如何使用 SqlDataReader 获取存储过程返回的分组数据?
【发布时间】:2016-05-09 05:44:30
【问题描述】:

我有一个由

定义的存储过程
CREATE PROCEDURE GetQuestionsGroupedBySection
    @survey_id INT
AS
    SELECT S.title, Q.qtext
    FROM Sections AS S INNER JOIN Questions AS Q 
         ON S.id = Q.section_id
         WHERE S.survey_id = @survey_id
         GROUP BY S.title;

相关表的定义位置

CREATE TABLE Questions (
    id INT IDENTITY(1,1),
    section_id INT,
    qtext NVARCHAR(300) NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY (section_id) REFERENCES Sections(id) ON DELETE CASCADE
);

CREATE TABLE Sections (
    id INT IDENTITY(1,1),
    title NVARCHAR(200) NOT NULL,
    survey_id INT,
    PRIMARY KEY (id),
    FOREIGN KEY (survey_id) REFERENCES Surveys(id) ON DELETE CASCADE
);

现在我正在尝试从我的服务器端代码中调用它,以获取 List 类型元素的分组

public class QuestionsBySection
{
    public string SectionTitle { get; set; }
    public List<string> SecionQuestions;
}

(或者是否有更好的数据结构可以使用?)。我有的是

    public List<QuestionsBySection> GetQuestionsAndSection (int survid)
    {
        // survid: survey id
        List<QuestionsBySection> AllQuestions = new List<QuestionsBySection>();
        using (SqlCommand cmd = new SqlCommand("GetQuestionsGroupedBySection", this._Conn))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("@survey_id", survid);
            this._Conn.Open();
            using ( SqlDataReader dataReader = cmd.ExecuteReader() )
            {
                while ( dataReader.Read() )
                {
                    // ... 
                }
            }
            this._Conn.Close();
        }
        return AllQuestions;
    }

但我不知道如何填写// ...。有什么提示吗?

【问题讨论】:

  • 您的存储过程似乎不是有效的 SQL(Q.qtext 上缺少分组或聚合)
  • @JoachimIsaksson 我有GROUP BY S.title;
  • SQL Server 在我尝试创建过程时提供Column 'Questions.qtext' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause。只有 MySQL 允许您选择一个字段而不对其进行聚合或分组。

标签: c# sql asp.net sql-server asp.net-mvc


【解决方案1】:

SQL 查询对 SQL Server 无效;使用 group by 子句时,所有选定的字段必须包含在 group by 子句中或者是一个聚合。根据您的预期结果,有几种方法可以返回 QuestionsBySection 的集合。

一种选择是返回展平的结果集,然后在应用层上聚合。

SProc 应该删除 group by 子句:

SELECT S.title, Q.qtext
FROM Sections AS S INNER JOIN Questions AS Q 
    ON S.id = Q.section_id
WHERE S.survey_id = @survey_id

检索时,需要对每一行进行评估,以查看 Title 是否已被使用:

var questions = new List<QuestionsBySection>();
// create sql connection
// execute command

while (dataReader.Read())
{
    string title = dataReader.GetString("title");
    string question = dataReader.GetString("qtext");

    QuestionsBySection qbs = questions.FirstOrDefault(x => x.SectionTitle.Equals(title , StringComparison.OrdinalIgnoreCase))
    if (qbs != null)
    {
        qbs.SecionQuestions.Add(question);
        continue;
    }

    qbs = new QuestionsBySection
    {
        SectionTitle = title,
        SecionQuestions = new List<string>{ question }
    }
    questions.Add(qbs);
}

还有其他几种实现结果的方法,但这应该能让您更好地了解如何汇总结果。

【讨论】:

    【解决方案2】:

    Sql group by 错误

    结果中有 2 列,但组中只有 1 列。您可以将第二列添加为按字段分组,也可以使用聚合(例如 min() 或 max())。

    SELECT S.title, qtext=max(Q.qtext)
        FROM .....
    

    数据读取器

    只需使用字段位置作为GetString的索引参数:

    var sTitle = dataReader.GetString(0);
    var sQuestion = dataReader.GetString(1);
    

    【讨论】:

      猜你喜欢
      • 2011-12-26
      • 2010-10-19
      • 2010-12-12
      • 2017-04-05
      • 1970-01-01
      • 2011-12-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      相关资源
      最近更新 更多