By following this recipe, we will learn how to use advanced SQL statements such as INNER JOIN
, COUNT
, LIKE
, DISTINCT
, and so on.
You can do a lot more than just perform simple queries of SQL database:
branch
, which is used to store the IDs and names of different branches of the dummy company:department
table, which stores the IDs and names of different departments of the dummy company, which is also linked to the branch data by the branch IDs:employee
table, which stores the information of all the employees in the dummy company. This table is similar to the one we used in the previous examples, except it has two more extra columns, namely birthday
and departmentID
:log
, which contains dummy records of the login time for each employee. The loginTime
column can be a timestamp
or date time
variable type:user
table that we also used in the previous examples:.pro
) and add the SQL module to your project:QT += core sql QT -= gui
main.cpp
and add the following header files to the top of the source file:#include <QSqlDatabase> #include <QSqlQuery> #include <QSqlError> #include <QDate> #include <QDebug>
void filterAge() { qDebug() << "== Employees above 30 year old ============="; QSqlQuery query; if (query.exec("SELECT name, age FROM employee WHERE age > 30")) { while (query.next()) { qDebug() << query.value(0).toString() << query.value(1).toString(); } } else { qDebug() << query.lastError().text(); } qDebug() << " "; }
void getDepartmentAndBranch() { qDebug() << "== Get employees' department and branch ============="; QSqlQuery query; if (query.exec("SELECT myEmployee.name, department.name, branch.name FROM (SELECT name, departmentID FROM employee) AS myEmployee INNER JOIN department ON department.id = myEmployee.departmentID INNER JOIN branch ON branch.id = department.branchID")) { while (query.next()) { qDebug() << query.value(0).toString() << query.value(1).toString() << query.value(2).toString(); } } else { qDebug() << query.lastError().text(); } qDebug() << " "; }
New York
branch and are below 30 years old:void filterBranchAndAge() { qDebug() << "== Employees from New York and age below 30 ============="; QSqlQuery query; if (query.exec("SELECT myEmployee.name, myEmployee.age, department.name, branch.name FROM (SELECT name, age, departmentID FROM employee) AS myEmployee INNER JOIN department ON department.id = myEmployee.departmentID INNER JOIN branch ON branch.id = department.branchID WHERE branch.name = 'New York' AND age < 30")) { while (query.next()) { qDebug() << query.value(0).toString() << query.value(1).toString() << query.value(2).toString() << query.value(3).toString(); } } else { qDebug() << query.lastError().text(); } qDebug() << " "; }
void countFemale() { qDebug() << "== Count female employees ============="; QSqlQuery query; if (query.exec("SELECT COUNT(gender) FROM employee WHERE gender = 1")) { while (query.next()) { qDebug() << query.value(0).toString(); } } else { qDebug() << query.lastError().text(); } qDebug() << " "; }
Ja
:void filterName() { qDebug() << "== Employees name start with 'Ja' ============="; QSqlQuery query; if (query.exec("SELECT name FROM employee WHERE name LIKE '%Ja%'")) { while (query.next()) { qDebug() << query.value(0).toString(); } } else { qDebug() << query.lastError().text(); } qDebug() << " "; }
August
:void filterBirthday() { qDebug() << "== Employees birthday in August ============="; QSqlQuery query; if (query.exec("SELECT name, birthday FROM employee WHERE MONTH(birthday) = 8")) { while (query.next()) { qDebug() << query.value(0).toString() << query.value(1).toDate().toString("d-MMMM-yyyy"); } } else { qDebug() << query.lastError().text(); } qDebug() << " "; }
27 April 2016
and displays their names on the terminal:void checkLog() { qDebug() << "== Employees who logged in on 27 April 2016 ============="; QSqlQuery query; if (query.exec("SELECT DISTINCT myEmployee.name, FROM (SELECT id, name FROM employee) AS myEmployee INNER JOIN user ON user.employeeID = myEmployee.id INNER JOIN log ON log.userID = user.id WHERE DATE(log.loginTime) = '2016-04-27'")) { while (query.next()) { qDebug() << query.value(0).toString(); } } else { qDebug() << query.lastError().text(); } qDebug() << " "; }
main()
function, connect our program to the MySQL database and call all the functions that we have defined in the previous steps. After that, close the database connection and we're done:int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("127.0.0.1"); db.setUserName("reonyx"); db.setPassword("reonyx"); db.setDatabaseName("testing"); if (db.open()) { filterAge(); getDepartmentAndBranch(); filterBranchAndAge(); countFemale(); filterName(); filterBirthday(); checkLog(); db.close(); } else { qDebug() << "Failed to connect to database."; } return a.exec(); }
A console application does not have any GUI at all and only shows you a text display in a terminal window. This is usually used in a backend system, as it uses fewer resources compared to a widget application. We use it in this example because it's faster to display the result without the need to place any widgets in the program, which we don't need in this case.
We separated the SQL queries into different functions so that it's easier to maintain the code and it doesn't become too messy. Do note that in C++, the functions have to be located before the main()
function, or they will not be able to be called by main()
.
The INNER JOIN
statement used in the preceding example joins two tables together and selects all rows from both tables, as long as there is a match between the columns in both tables. There are many other types of JOIN
statement that you can use in MySQL (and some other types of SQL architecture), such as LEFT JOIN
, RIGHT JOIN
, FULL OUTER JOIN
, and so on. The following diagram shows the different types of JOIN
statements and their effects:
LIKE
statement is normally used to search for a string variable in the database without the full word. Notice that there are two %
symbols, located before and after the search keyword.DISTINCT
statement used in the previous example filters out results that have the exact same variable. For example, without the DISTINCT
statement, you will see two versions of Larry King appear in the terminal because there are two records of him logging in to the system on the same day. By adding the DISTINCT
statement, MySQL will eliminate one of the repeating results and ensure every result is unique.d-MMMM-yyyy
stands for and why we used it in the preceding example. That is actually an expression supplied to the QDateTime
class in Qt to display the date time result using a given format. In this case, it will change the date time data that we get from MySQL, 2016-08-06
, to the format that we specified, resulting in 6-August-2016
. For more information, check out Qt's documentation at http://doc.qt.io/qt-5/qdatetime.html#toString, which has the full list of expressions that can be used to determine the format of the date and time string.18.217.147.193