【问题标题】:Group by multiple columns on a single MySql stored procedure在单个 MySql 存储过程中按多列分组
【发布时间】:2018-11-01 07:48:47
【问题描述】:

我有以下存储过程,用于显示多个 ASP 图表项的数据。

CREATE DEFINER=`root`@`localhost` PROCEDURE `GetChartApprovedData`(in siteValue varchar(45),
in skillValue varchar(100), in shiftValue varchar(100), in tmValue varchar(45), 
in grpmValue varchar(45), in dateValue date, in dateValue1 date)
BEGIN
SELECT count(agentlogin) AS totalApproved, shift AS Shift, skill AS Skill, tm AS TM, grpM AS GrpM
   FROM approved
   WHERE (sitevalue IS NULL
           OR site = sitevalue)
         AND (skillvalue IS NULL
               OR skill = skillvalue)
         AND (shiftvalue IS NULL
               OR shift = shiftvalue)
         AND (tmValue IS NULL
                OR tm = tmValue)
         AND (grpmValue IS NULL
                OR grpM = grpmValue)
         AND (dateValue IS NULL
                OR date BETWEEN dateValue AND dateValue1)
                group by shift, skill;
END

当我使用上述存储过程在 ASP 图表中显示数据时,我得到以下结果

两个图表都给出了相同的分组结果。我想要的是第一个图表我希望它按班次分组,而第二个图表我希望它按技能分组。是否可以在不为两者使用单独的存储过程的情况下实现这一目标?请告诉我。在此先感谢:)

private void GetChartData()
{
    string MyConString = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
    MySqlConnection con = new MySqlConnection(MyConString);
    MySqlCommand cmd = new MySqlCommand("GetChartApprovedData");
    cmd.CommandType = CommandType.StoredProcedure;
    string siteValue = null;
    DateTime? dateValue = null;
    DateTime? dateValue1 = null;
    if (ddlSite.SelectedValue != null && ddlSite.SelectedValue != "0")
    {
       siteValue = ddlSite.SelectedValue;
    }
    if (ViewState["Date"] != null && ViewState["Date"].ToString() != "0")
    {
        dateValue = DateTime.Parse(ViewState["Date"].ToString());
    }
    if (ViewState["Date1"] != null && ViewState["Date1"].ToString() != "0")
    {
        dateValue1 = DateTime.Parse(ViewState["Date1"].ToString());
    }
    cmd.Parameters.AddWithValue("siteValue", siteValue);
    cmd.Parameters.AddWithValue("dateValue", dateValue);
    cmd.Parameters.AddWithValue("dateValue1", dateValue1);
    cmd.Connection = con;
    con.Open();
    MySqlDataReader myread = cmd.ExecuteReader();
    while (myread.Read())
    {
        this.Chart2.Series["Series1"].Points.AddXY(myread["Shift"], myread["totalApproved"]);
        Chart2.Series["Series1"].IsValueShownAsLabel = true;
        Chart2.Series["Series1"].Label = "#VALY(#PERCENT)";
        Chart2.Series["Series1"].ToolTip = "Shift: #VALX \\nCount: #VALY";
        Chart2.ChartAreas["ChartArea1"].AxisX.LabelStyle.Interval = 1;
        Chart2.Legends.Clear();
        Chart2.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = false;
        Chart2.ChartAreas["ChartArea1"].AxisY.MajorGrid.Enabled = false;
        Chart2.Series["Series1"].Color = Color.DarkOrange;


        this.Chart1.Series["Series1"].Points.AddXY(myread["Skill"], myread["totalApproved"]);
        Chart1.Series["Series1"].IsValueShownAsLabel = true;
        Chart1.Series["Series1"].Label = "#VALY(#PERCENT)";
        Chart1.Series["Series1"].ToolTip = "Skill: #VALX \\nCount: #VALY";
        Chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Interval = 1;
        Chart1.Series["Series1"].Color = Color.DarkOrange;
        Chart1.Series["Series1"].LabelBackColor = Color.White;
        Chart1.Legends.Clear();
        Chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = false;
        Chart1.ChartAreas["ChartArea1"].AxisY.MajorGrid.Enabled = false;
   }
   con.Close();
}

【问题讨论】:

    标签: mysql stored-procedures


    【解决方案1】:

    是的,可以使用Dynamic SQL。我们可以创建一个查询字符串,然后准备并执行它。这将允许我们指定动态列名,这是不可能的。

    您还需要使用另外一个参数来指定在Group By 中使用哪一列

    DELIMITER $$
    
    CREATE DEFINER=`root`@`localhost` 
      PROCEDURE `GetChartApprovedData`(in siteValue varchar(45),
                                       in skillValue varchar(100), 
                                       in shiftValue varchar(100), 
                                       in tmValue varchar(45), 
                                       in grpmValue varchar(45), 
                                       in dateValue date, 
                                       in dateValue1 date, 
                                       in groupByColumn varchar(64)) 
    -- add extra in parameter, groupByColumn, to specify which column to group upon 
    
    BEGIN
    
    SET query_str = CONCAT('SELECT 
                              count(agentlogin) AS totalApproved, 
                              shift AS Shift, 
                              skill AS Skill, 
                              tm AS TM, 
                              grpM AS GrpM
                            FROM approved
                            WHERE (sitevalue IS NULL
                                   OR site = sitevalue)
                              AND (skillvalue IS NULL
                                   OR skill = skillvalue)
                              AND (shiftvalue IS NULL
                                   OR shift = shiftvalue)
                              AND (tmValue IS NULL
                                   OR tm = tmValue)
                              AND (grpmValue IS NULL
                                   OR grpM = grpmValue)
                              AND (dateValue IS NULL
                                   OR date BETWEEN dateValue AND dateValue1)
                            GROUP BY ', 
                            groupByColumn); -- concatenate the group by column param
    
    -- prepare the query
    PREPARE stmt FROM query_str;
    
    -- execute the query
    EXECUTE stmt;
    
    -- Clear up
    DEALLOCATE PREPARE stmt;
    
    END $$
    
    DELIMITER ;
    

    【讨论】:

    • 我们如何获得 'groupByColumn' 的值?
    • @prkash 你把它作为参数传递给你的存储过程。
    • 那我得为每张图表分别创建单独的mysql命令和传递参数,代码行太多了。
    • @prkash 所有参数都有哪些?
    • 我刚刚将 c# 代码添加到问题中。因此,在 myread 中,如果它读取技能列,我希望它按技能分组,如果它读取 shift,我希望它按 shift 列分组。
    【解决方案2】:

    解决问题的一种方法是在过程中执行两个查询(一个查询GROUP BY shift,一个查询GROUP BY技能,并在结果中使用标志来指示结果是否是按班次分组的数据或技能:

    CREATE DEFINER=`root`@`localhost` PROCEDURE `GetChartApprovedData`(in siteValue varchar(45),
    in skillValue varchar(100), in shiftValue varchar(100), in tmValue varchar(45), 
    in grpmValue varchar(45), in dateValue date, in dateValue1 date)
    BEGIN
    SELECT 'skill' AS type, count(agentlogin) AS totalApproved, skill AS Skill, tm AS TM, grpM AS GrpM
       FROM approved
       WHERE (sitevalue IS NULL
               OR site = sitevalue)
             AND (skillvalue IS NULL
                   OR skill = skillvalue)
             AND (shiftvalue IS NULL
                   OR shift = shiftvalue)
             AND (tmValue IS NULL
                    OR tm = tmValue)
             AND (grpmValue IS NULL
                    OR grpM = grpmValue)
             AND (dateValue IS NULL
                    OR date BETWEEN dateValue AND dateValue1)
                    group by skill;
    SELECT 'shift' AS type, count(agentlogin) AS totalApproved, shift AS Shift, tm AS TM, grpM AS GrpM
       FROM approved
       WHERE (sitevalue IS NULL
               OR site = sitevalue)
             AND (skillvalue IS NULL
                   OR skill = skillvalue)
             AND (shiftvalue IS NULL
                   OR shift = shiftvalue)
             AND (tmValue IS NULL
                    OR tm = tmValue)
             AND (grpmValue IS NULL
                    OR grpM = grpmValue)
             AND (dateValue IS NULL
                    OR date BETWEEN dateValue AND dateValue1)
                    group by shift;
    END
    

    然后在您的 c# 代码中,您将更改以下几行:

        this.Chart2.Series["Series1"].Points.AddXY(myread["Shift"], myread["totalApproved"]);
        this.Chart1.Series["Series1"].Points.AddXY(myread["Skill"], myread["totalApproved"]);
    

    到:

    if (myread["Type"] == "shift") {
         this.Chart2.Series["Series1"].Points.AddXY(myread["Shift"], myread["totalApproved"]);
    }
    if (myread["Type"] == "skill") {
         this.Chart1.Series["Series1"].Points.AddXY(myread["Skill"], myread["totalApproved"]);
    }
    

    【讨论】:

      【解决方案3】:

      如果您只是想减少 c# 代码大小,则可以使用 Madhu Bhaiya 提供的存储过程和下面的代码来达到预期的效果:

          private void GetChartData()
          {
              string MyConString = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
              MySqlConnection con = new MySqlConnection(MyConString);
      
      
              //PTK: TypeOfChartValue should be change with chart type you are using (I did not know what chart library you are using in your code
              Dictionary<string, TypeOfChartValue> charts = new Dictionary<string, Chart>()
              {
                  { "shift", this.Chart2 },  //PTK: the first value here is a column name to use in group by , the second is the chart to fill with resulted data. this line means that the Chart2 must be filled with data grouped by  'shift'
                  { "skill", this.Chart1 }  //PTK: the first value here is a column name to use in group by , the second is the chart to fill with resulted data. this line means that the Chart1 must be filled with data grouped by  'skill'
                  //PTK: you can add here as many charts as you wish
              };
              foreach (string groupby in charts.Keys)
              {
                  //PTK: TypeOfChartValue should be change with chart type you are using (I did not know what chart library you are using in your code
                  TypeOfChartValue chart = charts[groupby];
      
                  MySqlCommand cmd = new MySqlCommand("GetChartApprovedData");
                  cmd.CommandType = CommandType.StoredProcedure;
                  string siteValue = null;
                  DateTime? dateValue = null;
                  DateTime? dateValue1 = null;
                  if (ddlSite.SelectedValue != null && ddlSite.SelectedValue != "0")
                  {
                      siteValue = ddlSite.SelectedValue;
                  }
                  if (ViewState["Date"] != null && ViewState["Date"].ToString() != "0")
                  {
                      dateValue = DateTime.Parse(ViewState["Date"].ToString());
                  }
                  if (ViewState["Date1"] != null && ViewState["Date1"].ToString() != "0")
                  {
                      dateValue1 = DateTime.Parse(ViewState["Date1"].ToString());
                  }
                  cmd.Parameters.AddWithValue("siteValue", siteValue);
                  cmd.Parameters.AddWithValue("dateValue", dateValue);
                  cmd.Parameters.AddWithValue("groupByColumn", groupby);
      
                  cmd.Connection = con;
                  con.Open();
                  MySqlDataReader myread = cmd.ExecuteReader();
                  while (myread.Read())
                  {
                      chart.Series["Series1"].Points.AddXY(myread["Shift"], myread["totalApproved"]);
                      chart.Series["Series1"].IsValueShownAsLabel = true;
                      chart.Series["Series1"].Label = "#VALY(#PERCENT)";
                      chart.Series["Series1"].ToolTip = "Shift: #VALX \\nCount: #VALY";
                      chart.ChartAreas["ChartArea1"].AxisX.LabelStyle.Interval = 1;
                      chart.Legends.Clear();
                      chart.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = false;
                      chart.ChartAreas["ChartArea1"].AxisY.MajorGrid.Enabled = false;
                      chart.Series["Series1"].Color = Color.DarkOrange;
      
                  }
                  con.Close();
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2014-11-10
        • 1970-01-01
        • 2014-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-19
        • 1970-01-01
        相关资源
        最近更新 更多