【问题标题】:How to select aggregated student / class data in Apache Derby?如何在 Apache Derby 中选择汇总的学生/班级数据?
【发布时间】:2017-10-03 11:58:09
【问题描述】:

我需要在我的 Java 应用程序中重现访问报告。 以下是要复制的访问报告。 主要关注的是按合同编号部分分组以及每个子部分页脚中的访问/总时间总计。

我已经花了很多时间玩 SQL select 语句,但还没有把它弄好。

我的SQL语句如下:

select 
max(all class_.class_number_) as "Contract Number",
max(all first_name_)|| ' ' ||  max(all last_name_)  as "Student Name",
max(all class_.class_) as "Class",
max(all  date(clock_in_time_)) as "Latest Date",
count( student_id_number_) as "visits",
Sum({fn timestampdiff(SQL_TSI_MINUTE,clock_in_time_, clock_out_time_)}) as "Total Time in Minutes"
from student_  
join class_ on class_id_ = class_.id_ 
group by student_id_number_

我的表架构是这样的:

我的查询结果是:

所以我的问题是如何格式化我的 Java Derby 选择语句,以将合同编号作为标题分隔数据? 我还想了解如何在每个标题下计算总访问次数和总时间。

更新

Brian's Suggestions 产生了这些奇怪的结果,对名称进行聚合:

Blag 要求创建表。这里是。对不起,我忘了添加它。

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package timeclock;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;



public  class CreateDB {
    public static final String DRIVER= "org.apache.derby.jdbc.EmbeddedDriver";
    public static final String JDBC_URL = "jdbc:derby:student_;create=true";
    public static void main(String[] args) throws ClassNotFoundException, SQLException
    {
        Class.forName(DRIVER);
        isTableExist("STUDENT_");



    }

    public static boolean isTableExist(String sTablename) throws SQLException{
        Connection connection = DriverManager.getConnection(JDBC_URL);
        if(connection!=null)
        {
            DatabaseMetaData dbmd = connection.getMetaData();
            ResultSet rs = dbmd.getTables(null, null, sTablename.toUpperCase(),null);
            if(rs.next())
            {
                System.out.println("Table "+rs.getString("TABLE_NAME")+" already exists !!");
            }
            else
            {

                Timestamp timeIn = new Timestamp(System.currentTimeMillis());
                Timestamp timeOut = new Timestamp(System.currentTimeMillis());
                connection.createStatement().execute("create table STUDENT_(id_ INT not null primary key GENERATED ALWAYS AS IDENTITY(START WITH 1, INCREMENT BY 1), first_name_ varchar(20), last_name_ varchar(20), student_id_number_ varchar(6), class_id_  INT, clock_in_time_ timestamp, clock_out_time_ timestamp)");
                System.out.println(" Students Table created");
                connection.createStatement().execute("create table CLASS_(id_ INT not null primary key GENERATED ALWAYS AS IDENTITY(START WITH 1, INCREMENT BY 1), class_ varchar(20), class_number_ INT )");
                System.out.println(" Class Table created");
                System.out.println(timeIn);


                String sql = "INSERT INTO STUDENT_ ( first_name_, last_name_,  student_id_number_, class_id_, clock_in_time_, clock_out_time_  ) VALUES ( ?, ?, ?, ?, ?, ? )  " ;
                PreparedStatement ps = connection.prepareStatement( sql );
                ps.setString( 1, "Ben" );
                ps.setString( 2, "Tester");
                ps.setObject( 3, "649619");
                ps.setObject( 4, "1");
                ps.setObject( 5 , timeIn ) ;
                ps.setObject( 6 , timeOut ) ;
                ps.executeUpdate();
                System.out.println(" Students record sucessfully inserted");
                //This inserts class table

                String sql2 = "INSERT INTO CLASS_ ( class_, class_number_) VALUES ( ?, ? )  " ;
                PreparedStatement ps1 = connection.prepareStatement( sql2 );
                ps1.setString( 1, "DBA");
                ps1.setObject( 2, 123456);
                ps1.executeUpdate();
                connection.commit();
                System.out.println(" Class record sucessfully inserted");
            }
            return true;
        }
        return false;
}
}

当创建一个新学生时,这是运行的类

 /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package timeclock;

import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import static timeclock.ClockIn.JDBC_URL;

/**
 *
 * @author jstil
 */
class CreateStudent extends JFrame implements ActionListener{
    private static JFrame frame = new JFrame("Add Student");
    private static JTextField firstEnter;
    private static JTextField lastEnter;
    private static JTextField idEnter;
    private static JComboBox classEnter;
    private JPanel panel;


    public CreateStudent(String studentId){
        JLabel AddLabel;
        JLabel AddLabel2;
        JLabel AddLabel3;
        JLabel AddLabel4;
        frame.setSize(500, 300);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        // add instructions
        AddLabel = new JLabel("Enter First Name :",JLabel.LEFT);
        AddLabel2 = new JLabel("Enter Last Name :",JLabel.LEFT);
        AddLabel3 = new JLabel("Enter your Student ID :", JLabel.LEFT);
        AddLabel4 = new JLabel("Pick the class you are here for from the menu :",JLabel.LEFT);
        firstEnter = new JTextField(20);
        lastEnter = new JTextField(20);
        idEnter = new JTextField(6);
        classEnter = new JComboBox();
        JButton submitButton = new JButton("Submit"); 
        // font for Submit Buton
        submitButton.setFont(new Font("Serif", Font.BOLD, 16));
        submitButton.addActionListener(this);
        // new panel  creation be cause ContentPane panel = frame.getContentPane(); has been depreciated
        panel = new JPanel();

        //Set up Gui
        SpringLayout layout = new SpringLayout();
        panel.setLayout(layout);
        layout.putConstraint(SpringLayout.WEST, AddLabel,
                       5,
                        SpringLayout.WEST, panel);
        layout.putConstraint(SpringLayout.NORTH, AddLabel,
                      50,
                           SpringLayout.NORTH, panel);
        // 
        layout.putConstraint(SpringLayout.WEST, firstEnter,
                       5,
                        SpringLayout.EAST, AddLabel);
        layout.putConstraint(SpringLayout.NORTH, firstEnter,
                      50,
                           SpringLayout.NORTH, panel);
        //
        layout.putConstraint(SpringLayout.WEST, AddLabel2,
                        5,
                        SpringLayout.WEST, panel);
        layout.putConstraint(SpringLayout.NORTH, AddLabel2,
                      90,
                           SpringLayout.NORTH, panel);
        //
        layout.putConstraint(SpringLayout.WEST, AddLabel3,
                        5,
                        SpringLayout.WEST, panel);
        layout.putConstraint(SpringLayout.NORTH, AddLabel3,
                      130,
                           SpringLayout.NORTH, panel);
        //
        layout.putConstraint(SpringLayout.WEST, lastEnter,
                       5,
                        SpringLayout.EAST, AddLabel2);
        layout.putConstraint(SpringLayout.NORTH, lastEnter,
                      90,
                           SpringLayout.NORTH, panel);
        //
        layout.putConstraint(SpringLayout.WEST, idEnter,
                       5,
                        SpringLayout.EAST, AddLabel3);
        layout.putConstraint(SpringLayout.NORTH, idEnter,
                      130,
                           SpringLayout.NORTH, panel);
        //
        layout.putConstraint(SpringLayout.WEST, AddLabel4,
                        5,
                        SpringLayout.WEST, panel);
        layout.putConstraint(SpringLayout.NORTH, AddLabel4,
                      180,
                           SpringLayout.NORTH, panel);
        //
        layout.putConstraint(SpringLayout.WEST, classEnter,
                       5,
                        SpringLayout.EAST, AddLabel4);
        layout.putConstraint(SpringLayout.NORTH, classEnter,
                      180,
                           SpringLayout.NORTH, panel);
        //
        layout.putConstraint(SpringLayout.WEST, submitButton,
                        380,
                        SpringLayout.WEST, panel);
        layout.putConstraint(SpringLayout.NORTH, submitButton,
                      210,
                           SpringLayout.NORTH, panel);


         // add content to swing
        panel.add(AddLabel);
        panel.add(AddLabel2);
        panel.add(AddLabel3);
        panel.add(AddLabel4);
        panel.add(firstEnter);
        panel.add(lastEnter);
        panel.add(idEnter);
        panel.add(classEnter);
        panel.add(submitButton); 
        //Display the window.
        try {
                ViewClass();
            } catch (ClassNotFoundException | SQLException ex) {
                Logger.getLogger(CreateStudent.class.getName()).log(Level.SEVERE, null, ex);
            }
        pack();
        frame.setContentPane(panel);
        frame.setVisible(true);

    }
    public void actionPerformed(ActionEvent evt) 
        {
            String blank = ("");
            String firstName = firstEnter.getText();
            String lastName = lastEnter.getText();
            String studentId =idEnter.getText();
            String className = classEnter.getSelectedItem().toString();
            String classId = null;
            try {
            classId = ClassIdSet(className);

            } catch (SQLException ex) {
            Logger.getLogger(CreateStudent.class.getName()).log(Level.SEVERE, null, ex);
            }
            int idOfClass = Integer.valueOf(classId);




            if (firstName.equals(blank))
            { 
                JOptionPane.showMessageDialog(null, "You forgot to add a First Name");

            }
            if (lastName.equals(blank))
            { 
                JOptionPane.showMessageDialog(null, "You forgot to add a Last Name");

            }



            System.out.println(firstName + "  and  " + lastName + " recorded" );

            try {
                TimeStamp(firstName, lastName, studentId, idOfClass);
            } catch (SQLException ex) {
                Logger.getLogger(CreateStudent.class.getName()).log(Level.SEVERE, null, ex);
            }
            frame.dispose();




        };
    public static void ViewClass() throws ClassNotFoundException, SQLException
        {

        //This inserts class table

            Connection connection3 = DriverManager.getConnection(JDBC_URL);


            String sql3 = "SELECT class_ FROM CLASS_ ORDER BY class_";

        try {


            PreparedStatement ps2 = connection3.prepareStatement(sql3);


            // execute select SQL stetement
            ResultSet rs = ps2.executeQuery();

            while (rs.next()) {

                String existingClass = rs.getString("class_");
                               // add to scrollpanel

                             classEnter.addItem(existingClass);



                System.out.println("classes loaded to combo box");


            }
                        ps2.close();
                        connection3.close();

        } catch (SQLException e) {

            System.out.println(e.getMessage());

        } 




        System.out.println(" Class record sucessfully retrieved");
      }
    public static void TimeStamp(String first, String last, String number, Integer classId)throws  SQLException 
    {
        // create time stamp
        Timestamp time = new Timestamp(System.currentTimeMillis());
        // look up class id based on name

        Connection connection2 = DriverManager.getConnection(JDBC_URL);
        String sql2 = "INSERT INTO STUDENT_ ( first_name_, last_name_,  student_id_number_, class_id_, clock_in_time_, clock_out_time_  ) VALUES ( ?, ?, ?, ?, ?,? )  " ;
        PreparedStatement ps1 = connection2.prepareStatement( sql2 );
        ps1.setString( 1, first );
        ps1.setString( 2, last );
        ps1.setString( 3, number );
        ps1.setObject( 4, classId );
        ps1.setObject( 5 , time ) ;
        ps1.setObject( 6 , null ) ;
        ps1.executeUpdate();
        connection2.commit();
        JOptionPane.showMessageDialog(null, "You are clocked in");
        System.out.println(" Student sucessfully clocked in");
        ps1.close();
        connection2.close();
    }
    private String  ClassIdSet(String name)throws  SQLException
    {
        Connection connection = DriverManager.getConnection(JDBC_URL);
        Statement stmt = connection.createStatement();

            String sql2 = "select ID_ from class_ where class_ = ? "; 
            PreparedStatement ps1 = connection.prepareStatement( sql2 );
             ps1.setString( 1, name);
            ResultSet result = ps1.executeQuery();
            if(!result.next()){
                System.out.println("No Data Found"); //data not exist
                return null;
            }
           else{
               String classId= result.getString("ID_");
                System.out.println("Class id is  "+ classId );
              return classId;
              }   


    }


}

【问题讨论】:

  • 学生是否允许您发布他们的数据?
  • 我不知道你在说什么。这是一个时钟程序。如果我需要允许显示学生何时去过实验室的打印件,那么美国有更大的问题无法在编程帮助论坛中解决
  • 我认为您想按 class_number_ 分组,而不是按 student_id_number_ 分组。报告的每个部分都收集单个类的所有行,然后报告 count(student_id_number_)sum(out_time-in_time) 等内容。
  • Brian,由于某种奇怪的原因,如果不将所有结果一对一地聚合,就不能在 Derby 中使用 Group by。我发布了建议的修复程序,如您所见,有些问题
  • 提供create table 和测试数据(或做一个sqlfiddle.com),我们无法测试查询...

标签: java sql select group-by derby


【解决方案1】:

这里有两个问题:

  1. student_ 表存储有关学生的数据以及有关他们上课的数据。这是非规范化的,这意味着每次学生上课时都会重复姓名和学生 ID 号。考虑引入一个student_class_ 映射表来存储课堂出勤数据(即学生和班级之间的链接以及上下班时间)。
  2. 页脚数据针对每个班级(合同)进行汇总,因此在该特定查询中包含学生姓名没有意义。

假设未对架构进行任何更改,您将需要两个单独的查询:一个用于单个学生数据,另一个用于每个班级的页脚数据。

查询 #1(学生数据)

SELECT class_.class_number_ AS "Contract Number",
       first_name_ || ' ' ||  last_name_ AS "Student Name",
       class_.class_ AS "Class",
       MAX(ALL DATE(clock_in_time_)) AS "Latest Date",
       COUNT(student_.id_) AS "visits",
       SUM({FN TIMESTAMPDIFF(SQL_TSI_MINUTE, clock_in_time_, clock_out_time_)})
         AS "Total Time in Minutes"
FROM student_  
JOIN class_ ON class_id_ = class_.id_ 
GROUP BY class_.id_, class_.class_number_, class_.class_, 
         student_id_number_, first_name_, last_name_

查询 #2(每个类的汇总页脚数据)

SELECT class_.class_number_ AS "Contract Number",
       COUNT(student_id_number_) AS "Total visits for this Contract Number",
       SUM({FN TIMESTAMPDIFF(SQL_TSI_MINUTE, clock_in_time_, clock_out_time_)})
           AS "Total time for this Contract Number"
FROM student_  
JOIN class_ ON class_id_ = class_.id_ 
GROUP BY class_.class_number_

【讨论】:

  • 感谢史蒂夫的回答。我最快要到星期一才有时间测试它。
  • 谢谢史蒂夫,这两个查询都有效,我将重新考虑规范化我的数据库。
  • 很高兴听到 - 很高兴它有所帮助。
猜你喜欢
  • 1970-01-01
  • 2017-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-24
相关资源
最近更新 更多