Hibernate select relevent data in one query - mysql

I am new to Hibernate.
This is a User table
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(16) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
| sex | char(1) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
This is my sample data
+----+-------+------+------+
| id | name | age | sex |
+----+-------+------+------+
| 1 | Amit | 20 | M |
| 2 | Sumit | 21 | M |
| 3 | Mohan | 22 | M |
| 4 | Ram | 26 | M |
| 5 | John | 22 | M |
| 6 | Sita | 19 | F |
+----+-------+------+------+
These are my queries:
select id from User where name="Amit" and age=20;
select id from User where name="Ram" and age=26;
select id from User where name="Mohan" and age=22;
select id from User where name="Sita" and age=19;
I can do this in hibernate by running 4 queries.
Is there any way by which I can do this in just one query?
Please tell the same can be done in mysql too.
Please help. Any clue, link or reference will be appreciable.
Thank you.

you can do this
select id , name ,age , sex from User
where (name,age) IN (('Amit','20'),('Ram', '26'),('Mohan', '22'),('Sita', '19'));
DEMO HERE

In sql ...
select name, id from User where ( name="Amit" and age=20)
or ( name="Ram" and age=26 )
or ( name="Mohan" and age=22 )
or ( name="Sita" and age=19 )

Related

How to show data from sql table to make one of columns value column header(date)

Hello I have 2 tables in mysql DB:
mysql> describe lvlsupdate;
+--------------+-------------+------+-----+-------------------+-------------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+-------------------+-------------------+
| LvlsUpdateId | int | NO | PRI | NULL | auto_increment |
| UID | int | NO | MUL | NULL | |
| Nick | varchar(30) | NO | | NULL | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
| Lvl | int | YES | | NULL | |
+--------------+-------------+------+-----+-------------------+-------------------+
5 rows in set (0.02 sec)
mysql> describe players;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| UID | int | NO | PRI | NULL | auto_increment |
| Nick | varchar(30) | NO | UNI | NULL | |
| Active | tinyint(1) | NO | | NULL | |
+--------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
In one of theme there is column date which includes timestamp value.
I'd like to create query that will show me data that there will be column Nick and 7 dates (today and 6 days before). And in each row there should be nick and lvl value from each of this dates in proper column.
For now, I've created query like this:
SELECT LvlsUpdate.nick, LvlsUpdate.lvl, LvlsUpdate.date
FROM LvlsUpdate
INNER JOIN Players ON LvlsUpdate.uid = Players.uid
WHERE Players.active = 1 AND LvlsUpdate.date > date_sub(now(), interval 7 day)
which shows me list of nicks, lvls, and date but there are duplicates of nicks, it looks like this:
+------------------+------+---------------------+
| nick | lvl | date |
+------------------+------+---------------------+
| Player1 | 124 | 2020-10-11 00:01:02 |
| Player1 | 125 | 2020-10-12 00:01:03 |
| Player1 | 125 | 2020-10-13 00:01:02 |
| Player2 | 233 | 2020-10-11 00:01:02 |
| Player2 | 233 | 2020-10-12 00:01:03 |
| Player2 | 233 | 2020-10-13 00:01:02 |
| Player3 | 164 | 2020-10-11 00:01:02 |
| Player3 | 164 | 2020-10-12 00:01:03 |
| etc....
There is reference between LvlsUpdate.UID and Players.UID. There is only 1 entry per player per day.
Is it possible to do it in sql?

Dsictint bi-directional relation

I have table that describes realtionships between other tables in database. Every user can have any file, and every file can have any user.
If I get one files' relations and I don't have this file relation to user, but user has relation to that file. I want to see that.
When both have relations to themselves I don't want to see twice records.
As an input I have record type and record id. How to achieve that?
Closure table:
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| record_id | int(11) | NO | | NULL | |
| record_type | varchar(200) | NO | | NULL | |
| second_record_id | int(11) | NO | | NULL | |
| second_record_type | varchar(200) | NO | | NULL | |
+--------------------+--------------+------+-----+---------+----------------+
Sample data:
+----+-----------+-------------+------------------+--------------------+
| id | record_id | record_type | second_record_id | second_record_type |
+----+-----------+-------------+------------------+--------------------+
| 1 | 1 | files | 1 | users |
| 2 | 2 | users | 1 | files |
| 3 | 3 | users | 1 | files |
| 4 | 2 | files | 1 | users |
| 5 | 1 | users | 1 | files |
| 6 | 1 | files | 3 | users |
+----+-----------+-------------+------------------+--------------------+
I've tried
SELECT * FROM closure
WHERE record_id=1 OR second_record_id = 1
AND record_type="files" OR second_record_type="files"
GROUP BY "files"
HAVING record_id=1 OR second_record_id=1
but it gets me one relation:
+----+-----------+-------------+------------------+--------------------+
| id | record_id | record_type | second_record_id | second_record_type |
+----+-----------+-------------+------------------+--------------------+
| 1 | 1 | files | 1 | users |
+----+-----------+-------------+------------------+--------------------+
My desired result would be:
+----+-----------+-------------+------------------+--------------------+
| id | record_id | record_type | second_record_id | second_record_type |
+----+-----------+-------------+------------------+--------------------+
| 1 | 1 | files | 1 | users |
| 2 | 2 | users | 1 | files |
| 6 | 1 | files | 3 | users |
+----+-----------+-------------+------------------+--------------------+
Sql fiddle
EDIT
I've dropped id column finally.
I think you just want to compare both the "1" and the "files" at the same type, for each record type. This should produce your desired result:
SELECT c.*
FROM closure c
WHERE (record_id = 1 and record_type = 'files') OR
(second_record_id = 1 and second_record_type = 'files');
You don't have aggregation function so the group by and the having clause are unuseful if you wondt distinct add distinct clause (but the use of id don't permit a proper work)
SELECT *
FROM closure
WHERE ( record_id=1 OR second_record_id = 1 )
AND (record_type="files" OR second_record_type="files" )
or
SELECT distinct record_id, record_type, second_record_id, second_record_type
FROM closure
WHERE ( record_id=1 OR second_record_id = 1 )
AND ( record_type="files" OR second_record_type="files" )

MySQL count 2 columns in a row and join with another query

I have a table visits like this:
+--------------+-------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| vis_id | int(11) | NO | | NULL | |
| unit | int(11) | NO | | NULL | |
| time_in | timestamp | NO | | CURRENT_TIMESTAMP | |
| time_out | timestamp | NO | | 0000-00-00 00:00:00 | |
| in_username | varchar(16) | NO | | NULL | |
| out_username | varchar(16) | NO | | NULL | |
+--------------+-------------+------+-----+---------------------+----------------+
and a table users like this:
+------------+-------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| fname | varchar(32) | NO | | NULL | |
| lname | varchar(32) | NO | | NULL | |
| date_added | timestamp | NO | | CURRENT_TIMESTAMP | |
| username | varchar(16) | NO | | NULL | |
| password | varchar(40) | NO | | NULL | |
| auth_level | int(1) | NO | | 1 | |
| last_login | timestamp | NO | | 0000-00-00 00:00:00 | |
+------------+-------------+------+-----+---------------------+----------------+
I want to be able to count how many times each user is in in_username AND out_username... The query I was using before looks like this:
select count(*) as "count", u.fname as "fname"
from visits v
inner join users as u on u.username = v.in_username
group by u.username order by u.fname
But that only returns how many in_username's there are... I'd like to have both in the same query if possible, so I could get results like this:
+----------+-----------+----------+
| count_in | count_out | fname |
+----------+-----------+----------+
| 118 | 224 | Bo |
| 27 | 64 | James |
| 147 | 138 | Jeremy |
| 23 | 37 | Jim |
| 182 | 172 | Robert |
| 120 | 158 | Tom |
+----------+-----------+----------+
Where count_in is how many times their username appears in visits.in_username, and count_out is how many times their username appears in visits.out_username
Everything I've tried with UNION seems to add the counts together, or removes rows for some reason. Any ideas?
Do a subquery to get each total, combine them with UNION, and then merge them with SUM().
SELECT SUM(count_in) count_in, SUM(count_out) count_out, fname
FROM (SELECT COUNT(*) count_in, 0 count_out, in_username fname
FROM visits v
GROUP BY fname
UNION
SELECT 0 count_in, COUNT(*) count_out, out_username fname
FROM visits v
GROUP BY fname) combined

MySQL select records from one table if their id AND username do not appear in a second table

I have two tables like this:
logbook:
+------------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date_added | timestamp | NO | | CURRENT_TIMESTAMP | |
| username | varchar(16) | NO | | NULL | |
| entry | longtext | NO | MUL | NULL | |
+------------+-------------+------+-----+-------------------+----------------+
and
read_logbook:
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| logbook_id | int(11) | NO | | NULL | |
| username | varchar(16) | NO | | NULL | |
+------------+-------------+------+-----+---------+----------------+
What I'd like to do is to select EVERYTHING from logbook, but only if the logbook.id AND logbook.username DO NOT appear in read_logbook.logbook_id and read_logbook.username, respectively.
I've experimented with some left-union-right queries, as well as some not in queries, and keep getting either thousands more results than expected, or no results at all.
Any thoughts?
EDIT - I'd run this for a specific username... so basically, if my username was jmd9qs, I'd want all results from logbook where read_logbook.id != logbook.id and read_logbook.username != jmd9qs
I hope that's clear enough...
EDIT - TEST DATA
The logbook:
mysql> select id, date_added, username from logbook order by id desc limit 10;
+----+---------------------+-----------+
| id | date_added | username |
+----+---------------------+-----------+
| 94 | 2013-09-03 14:54:25 | tluce |
| 93 | 2013-09-03 13:12:02 | tluce |
| 92 | 2013-09-03 11:42:14 | tluce |
| 91 | 2013-09-03 08:28:20 | jmd9qs |
| 90 | 2013-09-03 07:13:36 | jmd9qs |
| 89 | 2013-09-03 07:05:19 | jmd9qs |
| 88 | 2013-09-03 06:57:47 | jsawtelle |
| 87 | 2013-09-03 06:15:42 | jsawtelle |
| 86 | 2013-09-03 05:21:14 | jsawtelle |
| 85 | 2013-09-03 03:52:25 | jsawtelle |
+----+---------------------+-----------+
Logbook entries that have been "marked" as read:
mysql> select logbook_id, username from read_logbook group by logbook_id desc limit 10;
+------------+----------+
| logbook_id | username |
+------------+----------+
| 94 | jmd9qs |
| 93 | jmd9qs |
| 92 | jmd9qs |
| 91 | jmd9qs |
| 90 | jmd9qs |
| 89 | jmd9qs |
| 88 | jmd9qs |
| 87 | jmd9qs |
| 86 | jmd9qs |
| 85 | jmd9qs |
+------------+----------+
10 rows in set (0.00 sec)
So when I run the query for jmd9qs, nothing should come up because in read_logbook, his username and the logbook id show up.
CLARIFICATION -
So in the logbook, the username is just the person who wrote logbook.entry. In read_logbook, username is the person who READ that entry. So if I'm logged in as jmd9qs, and I try to view the logbook, since I've read everything no logbook.entry's should come up. But for another user who HASN'T read that specific entry, the entry WOULD show up.
SELECT *
FROM logbook
WHERE logbook.username NOT IN
(SELECT read_logbook.username
FROM read_logbook
WHERE read_logbook.username='jmd9qs')
AND logbook.id NOT IN
(SELECT read_logbook.logbook_id
FROM read_logbook);
If I understand your needs, you should try
SELECT t1.* FROM logbook t1
LEFT JOIN read_logbook t2
ON t1.id = t2.id AND t1.username = t2.username
WHERE t2.id IS NULL AND t2.username IS NULL

Help with MySQL join 3 Tables

I am working on a registration system that uses the following tables:
Person (name etc.), Course (course date), Registration (association table pid, cid)
Person
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | text | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
Example Data:
select * from person;
+-----+--------+
| id | name |
+-----+--------+
| 101 | Graham |
| 102 | Lisa |
| 103 | John |
+-----+--------+
Course
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | text | YES | | NULL | |
| date | date | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
select * from course;
+----+---------+------------+
| id | name | date |
+----+---------+------------+
| 1 | Hip Hop | 2011-06-08 |
| 2 | Dancing | 2006-06-23 |
| 3 | Running | 2007-07-08 |
+----+---------+------------+
Registration
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| pid | int(11) | YES | | NULL | |
| cid | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
select * from registration;
+----+------+------+
| id | pid | cid |
+----+------+------+
| 1 | 101 | 1 |
| 2 | 101 | 2 |
| 3 | 103 | 2 |
+----+------+------+
I would like to find person(s) that have no registration records within the past two years. I am attempting to join the tables based on date calculation but it does not seem to work this way. Is this possible with mysql or is my approach of trying this with one query wrong?
query I have come up with:
select * from
(person left join registration on person.id = registration.pid)
left join course on course.id = registration.cid
AND DATE_FORMAT(`course`.`date`, "%m.%Y") > DATE_FORMAT( DATE_SUB(NOW(), INTERVAL 2 YEAR),"%m.%Y")
WHERE
registration.id IS NULL;
+-----+------+------+------+------+------+------+------+
| id | name | id | pid | cid | id | name | date |
+-----+------+------+------+------+------+------+------+
| 102 | Lisa | NULL | NULL | NULL | NULL | NULL | NULL |
+-----+------+------+------+------+------+------+------+
It should list person 102 and 103 since both registrations are older than 2 years and no other records of newer course dates can be found...
Give this a shot, using a NOT EXISTS clause:
select p.* from person p
where not exists (select 1 from person px
join registration rx on px.id = rx.pid
join course cx on rx.cid = cx.id
where px.id = p.id
and cx.date > DATE_SUB(NOW(), INTERVAL 2 YEAR))