JOIN 2 tables and select specific rows - java

I use Wordpress table to populate the javafx TableView.
In WP db I have 2 tables wp_posts & wp_postmeta and I need JOIN the table by ID (post_id in wp_postmeta) and select specific rows from wp_postmeta (not all).
For Exampe:
wp_postmeta structure post_id, meta_key, meta_value. In meta_key there is 3 rows - _yoast_wpseo_title, ._yoast_wpseo_metadesc, ._yoast_wpseo_focuskeywords
and I need this rows value from column meta_value.
My code:
ResultSet rs = connection.createStatement().executeQuery(" SELECT wp_postmeta._yoast_wpseo_title, wp_postmeta._yoast_wpseo_metadesc, wp_postmeta._yoast_wpseo_focuskeywords, wp_posts.post_title, wp_posts.post_name FROM wp_postmeta INNER JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id ");
And of course I receive error that columns _yoast_wpseo_title, _yoast_wpseo_metadesc, _yoast_wpseo_focuskeywords not found because thay are rows.
How I can do this? (I use java9, javafx, mysql jdbc). Or may be I must use PreparedStatement?
Screenshot:

Since you want to filter your query based on the content of the meta_key field, you use a WHERE clause:
SELECT wp_postmeta.meta_key, wp_postmeta.meta_value, wp_posts.post_title
FROM wp_postmeta INNER JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id
WHERE wp_postmeta.meta_key IN ('_yoast_wpseo_title', '_yoast_wpseo_metadesc', '_yoast_wpseo_focuskeywords')
You are providing a list of the meta keys you want to match. This will give (up to) three rows for each post.
If you want only one row for each post, things get more complicated (and probably aren't worth the trouble). You can use GROUP BY post_id and then study the Aggregate functions.

Related

Insert values in many to many relationship tables with JOOQ

I have three tables in my database, SUBSCRIPTION, USER_ID, and an association table called SUBSCRIPTION_USER_ID.
My strategy is to use JOOQ batch with three queries, the first one to insert on row into SUBSCRIPTION, the second query to insert multiple rows into USER_ID, and finally, I need to insert the association IDs into SUBSCRIPTION_USER_ID, so I did the following:
InsertValuesStep2 insertUserIds = insertInto(
USER_ID, USER_ID.USER_ID_TYPE, USER_ID.USER_ID_VALUE);
for (String userId : subscriptionDTO.getUserId())
insertUserIds = insertUserIds.values(getValue(0, userId), getValue(1, userId));
InsertReturningStep insertReturningUserIds = insertUserIds.onConflictDoNothing();
InsertResultStep insertReturningSubscription = insertInto(SUBSCRIPTION)
.set(SUBSCRIPTION.CHANNEL_ID, subscriptionDTO.getChannel())
.set(SUBSCRIPTION.SENDER_ID, subscriptionDTO.getSenderId())
.set(SUBSCRIPTION.CATEGORY_ID, subscriptionDTO.getCategory())
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
.onConflictDoNothing()
.returningResult(SUBSCRIPTION.ID);
Unfortunately, to insert values into the association table, I tried many ways but nothing works for me, finally, I tried to insert values in SUBSCRIPTION_USER_IDusing with select but It doesn't work:
InsertValuesStep insertValuesSubscriptionUserIds = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID)
.from(SUBSCRIPTION)
.innerJoin(USER_ID)
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))));
Am I missing something above? Is there a better way using JOOQ to insert many-to-many relationship values or to use queries results as parameters for other queries?
I'm assuming you posted your entire code. In case of which:
You don't call execute on your USER_ID insertion
Simply add
insertUserIds.onConflictDoNothing().execute();
Or alternatively, fetch the generated IDs using a call to returning().fetch()
Inner join
This might just be a stylistic question, but what you seem to be doing is a cross join. Your INNER JOIN filters aren't really join predicates. I'd put them in the WHERE clause. Clarity may help avoid further problems in such a query.
Specifically, that first "join predicate" is very confusing, containing a CONCAT call, which isn't something one would see in an INNER JOIN every day, and only touches one table, not both:
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
Wrong predicate
That last predicate seems wrong. You're inserting:
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
But you're querying
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getContactId()))));
That should probably be subscriptionDTO.getToken() again
As mentioned above, I have inserted values for SUBSCRIPTION and USER_ID tables. And get for the association table I need to get the IDs of the already inserted values from the above two tables, so to solve the issue I've used this query to insert in SUBSCRIPTION_USER_ID:
InsertReturningStep insertReturningSubscriptionUserId = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID).from(SUBSCRIPTION
.where(concat(USER_ID.USER_ID_TYPE, val(CATEGORY_USER_ID_DELIMITER), USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId()))
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))).onConflictDoNothing();
Finally, I have executed all the queries using batch:
using(configuration).batch(insertReturningSubscription,
insertReturningUserIds,
insertReturningSubscriptionUserId).execute()

MySql and java {getting related tables columns}

I have created 2 tables in MySQL [items, orderList], the foreign key id in orderlist references the primary key id in items. Now I want to take all columns{id, name, price (in Items), and quantity (in orderList)} from 2 tables in Java, how can I show id once because when I query data it shows id from both tables?
You can do with join queries, try the below query and select the fields whatever you want from two tables
SELECT items.id, items.name, items.price, orderList.quantity
FROM items INNER JOIN orderList ON items.id = orderList.id
In order to fetch the data only once, you need to mention where it should come from. You can try the following:
SELECT I.ID, I.NAME, I.PRICE, O.QUANTITY FROM ORDERLIST O, ITEMS I WHERE I.ID = O.ID
Here we have given aliases to both the tables and we have mentioned that the ID column will be picked from the ITEMS table.

Spring JPA Method name for a 2 table query using #Query

EDITTED
Curious... I have a custom Spring JPA query which I'm not sure how to write.
I'm extending PagingAndSortingRepository
The #Query: select * from Table1 tb1 JOIN Table2 tb2 on tb1.id = tb2.tb1_id
where tb2.personId = :personId and tb1.mainId=:mainId and tb2.status in (:statusList)
I'm not sure how to create the method name for this as it keeps giving me an error saying it can't find status in the Table1.
I figured something like:
public Page findByMainIdAndStatusInAndPersonId(#Param("mainId") Integer mainId, ..........); would work but it's telling me it can't find status. Which is understandable since status is in the Table2 object which I'm trying to join on.
**Table1**
id
column1
column2
mainId
List<Table2> table2List
**Table2**
id
table1_id
status
person_id
table 1 and 2 are linked via table2's table_id column. however in the Table1 JPA repository, I need to fetch all of Table1 based on criteria in Table2.
I checked "property expressions" but I'm not catching how to write the jpa method name
Thanks guys :)
After a while of looking around and trying different things... ANSWER:
When you want to query on Table2, you need to add it to the method as:
findBymainIdAndTable2List_StatusInAndTable2List_personId
So essentially add the list name followed by underscore and the column name in that table. If anyone wants to add more, def feel free :D This is how I got it to work

Insert into SQLite database if not exist in Java [duplicate]

I have an SQLite database. I am trying to insert values (users_id, lessoninfo_id) in table bookmarks, only if both do not exist before in a row.
INSERT INTO bookmarks(users_id,lessoninfo_id)
VALUES(
(SELECT _id FROM Users WHERE User='"+$('#user_lesson').html()+"'),
(SELECT _id FROM lessoninfo
WHERE Lesson="+lesson_no+" AND cast(starttime AS int)="+Math.floor(result_set.rows.item(markerCount-1).starttime)+")
WHERE NOT EXISTS (
SELECT users_id,lessoninfo_id from bookmarks
WHERE users_id=(SELECT _id FROM Users
WHERE User='"+$('#user_lesson').html()+"') AND lessoninfo_id=(
SELECT _id FROM lessoninfo
WHERE Lesson="+lesson_no+")))
This gives an error saying:
db error near where syntax.
If you never want to have duplicates, you should declare this as a table constraint:
CREATE TABLE bookmarks(
users_id INTEGER,
lessoninfo_id INTEGER,
UNIQUE(users_id, lessoninfo_id)
);
(A primary key over both columns would have the same effect.)
It is then possible to tell the database that you want to silently ignore records that would violate such a constraint:
INSERT OR IGNORE INTO bookmarks(users_id, lessoninfo_id) VALUES(123, 456)
If you have a table called memos that has two columns id and text you should be able to do like this:
INSERT INTO memos(id,text)
SELECT 5, 'text to insert'
WHERE NOT EXISTS(SELECT 1 FROM memos WHERE id = 5 AND text = 'text to insert');
If a record already contains a row where text is equal to 'text to insert' and id is equal to 5, then the insert operation will be ignored.
I don't know if this will work for your particular query, but perhaps it give you a hint on how to proceed.
I would advice that you instead design your table so that no duplicates are allowed as explained in #CLs answer below.
For a unique column, use this:
INSERT OR REPLACE INTO tableName (...) values(...);
For more information, see: sqlite.org/lang_insert
insert into bookmarks (users_id, lessoninfo_id)
select 1, 167
EXCEPT
select user_id, lessoninfo_id
from bookmarks
where user_id=1
and lessoninfo_id=167;
This is the fastest way.
For some other SQL engines, you can use a Dummy table containing 1 record.
e.g:
select 1, 167 from ONE_RECORD_DUMMY_TABLE

JPA/Hibernate query construction

I am fetching records from my "record" table. "record" table has many columns tow of which are
client_id, foreign key mapping to client table.
creation_date , date of record creation
I would like to do a query on this table , but I would like to fetch only one record per client(latest creation_date record has preference).
Will following work?
select r.id,r.xx,r.yy
group by(r.client_id),r.creation_date
from record r
order by creation_date desc
I tried above and seems records fetched are not of latest creation dates.
Hope my question is clear
Just keep your query and add a WHERE condition :
SELECT r.id,r.xx,r.yy
GROUP BY(r.client_id)
FROM record r
WHERE r.creation_date = (SELECT MAX(creation_date) FROM record tmp WHERE tmp.client_id = r.client_id )
Take a look at This discussion
This should give you a good starting point in HQL.
from Record as r inner join fetch r.client
where r.creation_date > (
select max(rec.creation_date) from Record rec
where rec.client.client_id = r.client.client_id
)
This of course assumes that your Record has a reference to its parent Client called client.

Categories

Resources