I have two oracle table:users and logs,as follow,
users:
---------
id number,
name varchar2(50)
logs:
-----
user_id number,
visit_date date
I need to find out the first 10 users who never appears in the logs table (means they never visit the page),I can write a sql:
select *
from users u
where not exists (
select 1 from logs o
where o.user_id = u.id)
and rownum<=10
But now the problem is these two table are not in the same schema,they could not be accessed for each other,so I can not join them.
Because there are two microservices,one microservice should query its own schema
If I fetch 10 records from users,maybe they all never visit the page,I need to fetch 10 more,then after that still 5 users did not visit that page,I need to fetch 5 more,and so on.So I am not sure how many record I should fetch at the first time.Is it a good idea to do so?And how to write the code?
If I fetch all the record of the 2 tables,then do join using Java code,I'm worried about the amount of data being too large.Or should I just make these two tables accessible to each other?
So,how to do paging with 2 table but not join them?
But now the problem is these two table are not in the same schema,they could not be accessed for each other,so I can not join them.
Create a user that can see both schemas and log in to that user and access the tables using schema_name.table_name:
SELECT *
FROM schema1.users u
WHERE NOT EXISTS (
SELECT 1
FROM schema2.logs l
WHERE l.user_id = u.id
)
ORDER BY u.something
FETCH FIRST 10 ROWS ONLY
or
SELECT *
FROM (
SELECT *
FROM schema1.users u
WHERE NOT EXISTS (
SELECT 1
FROM schema2.logs l
WHERE l.user_id = u.id
)
ORDER BY u.something
)
WHERE ROWNUM <= 10
Alternatively, create a third schema and GRANT the SELECT privilege on the USERS and LOGS tables in the first two schemas and then create a view in that third schema and a new micro-service and use that.
Related
I want to fetch the data from following tables such that i do not have to call multiple queries and set the attribute of response isLikedByUser. userId i am sending in the request.
Posts -- Table Name
userId,
postId,
text,
likesCount,
commentsCount
LikeMapping -- Table Name
userId,
postid
Now I wrote query and fetched data from first table based on userId. Then iterated on each row and for each postId and userId from request found rows in Table 2 and if data is found I set the attribute of isLikedByUser.
How can I write the query which can help me to fill the attribute value without writing query in loop.
Thanks
To clarify more isLikedByUser is only the response attribute no column in any table and want to set it as true or false if mapping is found in second table.
Use a LEFT JOIN on a sub-query together with COALESCE to get a true/false (1/0) flag if the user has liked own post or not for each post by the given user
SELECT p.*, COALESCE(isLikedByUSer, 0)
FROM Posts p
LEFT JOIN (SELECT 1 isLikedByUser, postId, userID FROM LikeMapping) as l ON l.postId = p.postId AND l.userId = p.userId
WHERE p.userId = 100
You need to use LEFT OUTER JOIN and CASE statement. Something like below should work.
Select p.*,
case count(lm.postid) when 0 then true else false end as isLikedByUser
from Posts p
LEFT OUTER JOIN LikeMapping lm ON p.postId = lm.postId
WHERE lm.userId = userIdFromRequest
group by userId, postId, text, likesCount, commentsCount;
This might be faster than the other Answers.
SELECT p.*,
lm.postid IS NOT NULL AS isLikedByUser
FROM Posts AS p
LEFT JOIN ( SELECT DISTINCT postid FROM LikeMapping ) AS lm
ON lm.postid = p.postid
What version of MySQL? This probably needs 5.6 or later.
Please provide EXPLAIN SELECT ... if you wish to discuss further.
I have three tables here.The user is able to apply the training available.when he/she selects the training then it is placed at TRAINUSER table according to his/her userID. I want to SELECT the user when he/she logs in and to show data from TRAINUSER table which he/she has not applied the training. Like user_id 1 has applied 2 and 3 training but has not applied 1 and 4 training. I want user_id 1 to show with training 1 and 4 using hibernate query.
Some of this will depend on what your domain classes look like, you could use executeQuery like so:
Training.executeQuery( "from Training tr where tr.id not in ( select t.id from TrainUser tu join tu.training t join tu.user u where u.username = :uname )", [uname: 'ADMIN'] )
Assuming the following domains, only relevant fields included:
class User {
String username
}
class TrainUser {
static hasMany = [training: Training, user: User]
}
class Training {
String name
}
I have a constant set of users that I want to filter out and apply to each query to look at what they are doing on an app. I have been poking and probing around here to get a better sense of how to do this, but it is still unclear to me. I am a newbie with SQL statements and JAVA. Any help, particularly explanation is highly welcomed.
I have been trying to figure it out using these two articles to no avail: 1 & 2; these examples show how you can create a query and use it in another query, which is what I am trying to do.
Someone mentions a wrap (see ref. 1) which is what i attempt to do:
Sure, wrap your two set operations in outer queries with selects that include fixed columns called Source, i.e. SELECT
'horrible_query_1' AS Source, * and SELECT 'ugly_query_2' AS Source,
*.
That way your UNION will give you all the columns from your query plus the source identifier.
My question: is it possible to repurpose these queries into separate queries without having to do joins with the variable? I don't understand how that works (I'm not sure I am saying it right either).
This is the User group and filter I want to repurpose across all queries:
<select id="get_num_x_users" resultClass="java.lang.Integer">
select count(distinct user_id) from positions sp
join position_definitions sd on sp.position_id = sd.id
where sd.position like '%catcher%'
or lower(sd.position) like '%pitcher%'
or lower(sd.position) like '%dh%';
</select>
Repurpose into this query (among a few others):
<select id="get_u_counts" resultClass="java.lang.Integer">
SELECT COUNT(DISTINCT u.id)
FROM searches s
JOIN users u
ON s.user_id = u.id
WHERE search_date > DATE_SUB(curdate(), INTERVAL 3 MONTH)
AND LENGTH(search_term) > 0
AND search_term NOT LIKE ' LIC: SPEC: %'
AND u.type != 'coach';
</select>
My attempt (That does not work when I am in mysql database):
with get_x_users as (
select count(distinct user_id) from positions sp
join position_definitions sd on sp.position_id = sd.id
where sd.position like '%catcher%'
or lower(sd.position) like '%pitcher%'
or lower(sd.position) like '%dh%';),
(SELECT COUNT(get_x_users)
FROM searches s
JOIN users u
ON s.user_id = u.id
AND get_x_users
WHERE search_date > DATE_SUB(curdate(), INTERVAL 3 MONTH)
AND LENGTH(search_term) > 0
AND u.type != 'coach');
In SQL we can join tables together using a common field. For instance, if you have a user_id field in two different tables you can match the records using that common field. You can also create a join that gives you all the records in one table and only those that match in the second table, that's what LEFT JOIN does.
Using this principle, you do a little reverse logic and create a query which gives you all the records from your search query (ExcludeQuery) and join it to the users whom you want to exclude. This will give you a list of records with and without matches to the excluded users. What you do then is use a where to only include the records that haven't matched an excluded user, WHERE ExcludeQuery.user_id IS NULL.
SELECT s.*
FROM searches s
JOIN users u
ON s.user_id = u.id
WHERE search_date > DATE_SUB(curdate(), INTERVAL 3 MONTH)
AND LENGTH(search_term) > 0 AND u.type != 'coach'
LEFT JOIN
(select user_id from positions sp
join position_definitions sd on sp.position_id = sd.id
where sd.position like '%catcher%'
or lower(sd.position) like '%pitcher%'
or lower(sd.position) like '%dh%') AS ExcludeQuery
ON ExcludeQuery.user_id=s.user_id
WHERE ExcludeQuery.user_id IS NULL
I have a simple Spring MVC Data project setup where I'm trying to select a list of users that don't already exist within an Admin table. Here's my repository method
SELECT u FROM User u WHERE u.id NOT IN (SELECT a.id FROM Admin a WHERE a.id = :id)
List<User>findAvailableUsers(#Param("id") Long id)
This works well, the more users I add to the Admin Table, the less I have available in my <select> tab
When it comes to editing an existing user in the Admin table, my <select> tag should contain all available Users to add as well as the currently mapped User, however because of the NOT IN clause this single user is omitted from the query results. Can I modify this query to include all available Users to add including the User that currently exists tag?
example: User 2 and User 4 have been added to the Admin table. When I edit the record for User 2 in that Admin table, I should still see User 2 as an available option, but it is omitted
Something like this?
SELECT u FROM User u WHERE u.id NOT IN (SELECT a.id FROM Admin a WHERE a.id = :id) OR u.id = :idToGet
I am using Hibernate 3.6
User is an entity class
Contact is an entity class
User has a Set<Contact>
The relationship is uni-directional and mapped as one-to-many.
I have tried out the following lazy loading and fetch combinations. Here is a list of my understanding and actual results
with session.get(User.class, <some userId>) or session.load(User.class, <some userId>)
lazy fetch result
* true join ignores lazy loading
* 1 select for retrieving the User and his contacts with a left outer join
* select 1 select for a User record
* 1 select for all contacts of the user
* subselect 1 select for a User record
* 1 select for all contacts of the user
* false join 1 select for retrieving the User and his contacts with a left outer join
* select 1 select for a User record
* 1 select for all contacts of the user
* subselect 1 select for a User record
* 1 select for all contacts of the user
with session.createQuery(from User)
lazy fetch result
* true join 1 select for all User records
* 1 select for each User record to retrieve their contacts
* respect lazy loading
* probable n + 1
* select 1 select for all User records
* 1 select for each User record to retrieve their contacts
* probable n + 1
* subselect 1 select for all User records
* 1 sub-select to retrieve all contact records in one go
* false join 1 select for all User records
* 1 select for each User record to retrieve their contacts
* probable n + 1
* select 1 select for all User records
* 1 select for each User record to retrieve their contacts
* probable n + 1
* subselect 1 select for all User records
* 1 sub-select to retrieve all contact records in one go
Here are a few questions I have:
Is my understanding correct ?
With session.get() when lazy=true, fetch=subselect why does not Hibernate execute a subselect ? I guess this is because it is absolutely un-necessary. Am I correct ?
With session.get() when lazy=false, fetch=subselect why does not Hibernate execute a subselect ? It should execute one here but it does not. I wonder why ?
With session.createQuery() when lazy=true, fetch=join why does Hibernate lazy load ? It did not do this earlier with session.get()
With session.createQuery() when lazy=false, fetch=join why does not Hibernate use a join ?
Thanks in advance
Ok people, after much digging this is what I can conclude. Just wanted to share my spoils with you all. If anyone feels they can add more to this, you are most welcome. Let me start with a sample data set.
The user table
--------------------------------------------------
USER_ID USERNAME
--------------------------------------------------
1 User One
2 User Two
3 User Three
The contact table
-------------------------------------------------------------------------------------------------------------------
CONTACTID TITLE FIRSTNAME LASTNAME CITY COUNTRY EMAIL USER_ID
-------------------------------------------------------------------------------------------------------------------
1 Mr. Clark Kent New York United States man-of-steel#anywhere.earth 1
2 Mr. Hank Ketcham Manhattan United States dennis-mitchell#somewhere.us 2
3 Mr. Tony Stark Malibu United States iron-man#anywhere.earth 2
4 Mr. Bruce Wayne Gotham United States dark-knight#gotham.us 2
Q2. With session.get() when lazy=true, fetch=subselect why does not Hibernate execute a subselect ? I guess this is because it is absolutely un-necessary. Am I correct ?
A2. Yes a subselect is absolutely un-necessary here. Here is what the subselect might look like
SELECT
u.USER_ID AS USER1_1_,
u.USERNAME AS USERNAME1_,
c.USER_ID AS USER15_1_1_,
c.CONTACTID AS CONTACTID1_,
c.CONTACTID AS CONTACTID0_0_,
c.TITLE AS TITLE0_0_,
c.FIRSTNAME AS FIRSTNAME0_0_,
c.LASTNAME AS LASTNAME0_0_,
c.CITY AS CITY0_0_,
c.COUNTRY AS COUNTRY0_0_,
c.EMAIL AS EMAIL0_0_,
FROM
user u,contact c
WHERE
u.USER_ID = 2
AND
c.USER_ID IN
(
SELECT USER_ID FROM user WHERE USER_ID = u.USER_ID
)
I do not see any benefit of executing a sub-select here over the current strategy of simply executing a seperate select for contact records. Infact, a subselect might be an un-necessary performance drain.
Q3. With session.get() when lazy=false, fetch=subselect why does not Hibernate execute a subselect ? It should execute one here but it does not. I wonder why ?
A3. Ok. Again here is what the sub-select might look like (exactly similar to the one above with some other id)
SELECT
u.USER_ID AS USER1_1_,
u.USERNAME AS USERNAME1_,
c.USER_ID AS USER15_1_1_,
c.CONTACTID AS CONTACTID1_,
c.CONTACTID AS CONTACTID0_0_,
c.TITLE AS TITLE0_0_,
c.FIRSTNAME AS FIRSTNAME0_0_,
c.LASTNAME AS LASTNAME0_0_,
c.CITY AS CITY0_0_,
c.COUNTRY AS COUNTRY0_0_,
c.EMAIL AS EMAIL0_0_,
FROM
user u,contact c
WHERE
u.USER_ID = 3
AND
c.USER_ID IN
(
SELECT USER_ID FROM user WHERE USER_ID = u.USER_ID
)
As you can see this will not yield any records since USER_ID=3 does not have any contact records. That defeats the whole purpose of doing session.get() for a User record wherein get() will return null inspite of having a valid User record in the table. So again, a seperate select for contact records is the only way out.
Q4. With session.createQuery() when lazy=true, fetch=join why does Hibernate lazy load ? It did not do this earlier with session.get()
Q5. With session.createQuery() when lazy=false, fetch=join why does not Hibernate use a join ?
Ans. My current understanding says that this maybe simply because Hibernate does not want to end up firing a join which selects a huge data set (comprising all User records and their Contact records) and loading a huge collection in-memory.