So I have this table named SAKAI_REALM_RL_FN that has 3 fields
REALM_KEY
ROLE_KEY
FUNCTION_KEY
What this statement needs to do is that if a certain 2 combinations of ROLE_KEY & FUNCTION_KEY don't exist for each REALM_KEY, than do an insert.
I was already taking a look at this StackOverflow post
I also have the query I was using for the singular inserts:
INSERT INTO `sakai`.`SAKAI_REALM_RL_FN` (`REALM_KEY`, `ROLE_KEY`, `FUNCTION_KEY`) VALUES (248620, 8, 308);
Psuedo-Code:
if(ROLE_KEY equals 8 and FUNCTION_KEY=308 don't exist for REALM_KEYS)
than insert ROLE_KEY=8 & FUNCTION_KEY=308
INSERT INTO `sakai`.`SAKAI_REALM_RL_FN` (`REALM_KEY`, `ROLE_KEY`, `FUNCTION_KEY`)
SELECT *primaryKey*
FROM `sakai`.`SAKAI_REALM_RL_FN`
WHERE not exists (SELECT *primaryKey*
from `sakai`.`SAKAI_REALM_RL_FN`
where role_key = 8 and function_key = 308);
Hope that helps...
I wasn't quite sure what you wanted, but here's something that you might find useful.
Schema with few entries:
CREATE TABLE ALOHA (
REALM_KEY VARCHAR(32) NOT NULL,
ROLE_KEY VARCHAR(32) NOT NULL,
FUNCTION_KEY VARCHAR(32) NOT NULL
);
INSERT INTO ALOHA VALUES ('1', '1', '1');
INSERT INTO ALOHA VALUES ('1', '1', '2');
INSERT INTO ALOHA VALUES ('1', '2', '1');
INSERT INTO ALOHA VALUES ('1', '2', '2');
INSERT INTO ALOHA VALUES ('1', '2', '3');
INSERT INTO ALOHA VALUES ('1', '2', '4');
Try to insert 3 entries (only one gets inserted):
INSERT INTO ALOHA (REALM_KEY, ROLE_KEY, FUNCTION_KEY)
SELECT * FROM (
SELECT '1' AS REALM_KEY, '2' AS ROLE_KEY, '1' AS FUNCTION_KEY
UNION ALL
SELECT '1', '2', '3'
UNION ALL
SELECT '1', '2', '5'
) s
WHERE NOT EXISTS
(SELECT 1 FROM ALOHA a
WHERE a.ROLE_KEY = s.ROLE_KEY
AND a.REALM_KEY = s.REALM_KEY
AND a.FUNCTION_KEY = s.FUNCTION_KEY);
The RDBMS is well-equipped to handle this, if you define the correct index.
Sounds like what you need is a compound UNIQUE index across all three columns. When you perform an INSERT IGNORE, the combination will be inserted if it does not already exist.
Note that this will fail if you already have non-unique rows in your table.
ALTER TABLE SAKAI_REALM_RL_FN ADD UNIQUE KEY `idx_unique_realm_role_function` (REALM_KEY, ROLE_KEY, FUNCTION_KEY)
Then the INSERT selects all the REALM_KEY values and static values for the other 2 columns. If the values already exist, they're ignored. Otherwise they are inserted along with the REALM_KEY.
INSERT IGNORE INTO SAKAI_REALM_RL_FN (REALM_KEY, ROLE_KEY, FUNCTION_KEY)
/* SELECT within INSERT gets all REALM_KEY plus the 2 static values */
SELECT
REALM_KEY,
8,
308
FROM SAKAI_REALM_RL_FN
Here's a demo
When you have completed the INSERT IGNORE, you can drop the UNIQUE KEY since it may no longer be needed.
ALTER TABLE SAKAI_REALM_RL_FN DROP KEY `idx_unique_realm_role_function`
Related
I had a statement in PSQL that did this just fine (based on an answer from this thread)
But I've been trying to recreate the same statement in MySQL which has been difficult. My current workaround is ugly:
CREATE TEMPORARY TABLE potential_duplicates (
id VARCHAR(64)
content TEXT,
) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
INSERT INTO potential_duplicates(id, content) VALUES ('1', 'some content'), ('2', 'some more content');
SELECT id, content FROM potential_duplicates WHERE id IN (SELECT id FROM main_table);
INSERT INTO main_table(id, content)
SELECT id, content FROM potential_duplicates WHERE id NOT IN (SELECT id FROM main_table);
This query is going to be used very often and I feel like making a temporary table every query is inefficient. Originally I was trying to find a way to use the INSERT ON DUPLICATE feature. It would have worked fine if I was just inserting and nothing else, but i need to return the duplicate values in the end.
Assuming id is a primary key (or at least unique), you can use INSERT IGNORE to avoid duplicates and RETURNING (available as of MariaDB 10.5) to return the inserted id values:
INSERT IGNORE main_content(id, content)
VALUES ('2', 'some content'), ('5', 'some more content')
RETURNING id
Demo on dbfiddle
I am implementing the full text search on table called programming_language.
It contains multiple rows with 'name' column such as java, javascript, etc.
Initially I didn't have full text index so I did the following:
ALTER TABLE `Example`.`programming_language`
ADD FULLTEXT INDEX `fi_name` (`name`) WITH PARSER ngram VISIBLE;
-- This returns nothing
After this, full text search seems to work for most of the rows. However, some words such as 'java' aren't found by query.
My sql look like following
select * from programming_language
where match(name)
against("java" IN NATURAL LANGUAGE MODE);
-- This returns nothing
or
select * from programming_language
where match(name)
against("java" IN BOOLEAN MODE);
-- This returns nothing
(also tried java* but didn't work as well)
I am expecting to get back java and javascript, but none of them get returned.
Is there anything wrong with my sql?
I am fairly new to this topic and would appreciate for any helps.
it is your parser ngram
Without it no problem
Schema (MySQL v8.0)
CREATE TABLE programming_language (
`word_id` INTEGER,
`name` VARCHAR(15)
);
ALTER TABLE `programming_language`
ADD FULLTEXT INDEX `fi_name` (`name`) ;
-- This returns nothing
INSERT INTO programming_language
(`word_id`, `name`)
VALUES
('1', 'SWIFT'),
('2', 'JAVA'),
('3', 'java'),
('4', 'SENTENCE'),
('5', 'PETITION'),
('6', 'CERTIFICATE'),
('7', 'AMENDMENT'),
('8', 'NOTIFICATION'),
('9', 'EXTRACT'),
('10', 'PETITION'),
('11', 'NOTIFICATION'),
('12', 'MANIFESTATION'),
('13', 'OTHER'),
('14', 'REPRESENTATIONS');
Query #1
select * from programming_language
where match(name)
against("java" IN NATURAL LANGUAGE MODE);
word_id
name
2
JAVA
3
java
Query #2
select * from programming_language
where match(name)
against("java" IN BOOLEAN MODE);
word_id
name
2
JAVA
3
java
View on DB Fiddle
Schema (MySQL v8.0)
CREATE TABLE programming_language (
`word_id` INTEGER,
`name` VARCHAR(15)
);
ALTER TABLE `programming_language`
ADD FULLTEXT INDEX `fi_name` (`name`) ;
-- This returns nothing
INSERT INTO programming_language
(`word_id`, `name`)
VALUES
('1', 'SWIFT'),
('2', 'JAVA'),
('3', 'java'),
('4', 'javascript'),
('5', 'PETITION'),
('6', 'CERTIFICATE'),
('7', 'AMENDMENT'),
('8', 'NOTIFICATION'),
('9', 'EXTRACT'),
('10', 'PETITION'),
('11', 'NOTIFICATION'),
('12', 'MANIFESTATION'),
('13', 'OTHER'),
('14', 'REPRESENTATIONS');
Query #1
select * from programming_language
where match(name)
against("java javascript" IN NATURAL LANGUAGE MODE);
word_id
name
4
javascript
2
JAVA
3
java
Query #2
select * from programming_language
where match(name)
against("java*" IN BOOLEAN MODE);
word_id
name
2
JAVA
3
java
4
javascript
View on DB Fiddle
An ngram is a contiguous sequence of n characters from a given sequence of text. The ngram parser tokenizes a sequence of text into a contiguous sequence of n characters. For example, you can tokenize “abcd” for different values of n using the ngram full-text parser.
So you need to configure ngram for 4 letter words https://dev.mysql.com/doc/refman/8.0/en/fulltext-search-ngram.html
IMPORTANT:
I'm really a rookie in using MYSQL.
I have to table, and I'm trying to use an update statement instead of using an insert statement to update a table, base on another table on a inner join query.
My first table looks like the following:
exp_credit_tracker_designation
id association_id designation_name
is base on the other table:
exp_credit_tracker_assoc:
id, credit_type, association_name, address, city, province, postal_code, country, cycle_type, cycle_begin, cycle_months
'1', '2', 'Association', '14 bloor street', 'Toronto', 'ON', 'M5S 2E5', 'US', '2', '1526356800', '7'
'2', '2', 'designation', '40 Willcocks St', 'Ottawa', 'BC', 'M5S 2E5', 'CA', '1', '1526356800', '3'
'3', '2', 'credit types', '85 St George St', 'Toronto', 'AL', 'M5S 2E5', 'US', '2', '1540008000', '3'
'4', '1', 'association', '46 muriel ave', 'St. John', 'NB', 'M5M 2L2', 'US', '1', '1526356800', '4'
'5', '1', 'designation', '10 king street', 'Toronto', 'ON', 'M5S 2E5', 'CA', '2', '1526529600', '9'
Now, as you can notice, the first table doesn't have any value at the moment and my hope is to automatically update my table with a INNER JOIN statement base on my update. Something in the line of:
UPDATE exp_credit_tracker_designation
INNER JOIN exp_credit_tracker_assoc ON exp_credit_tracker_designation.assocaition_id = exp_credit_tracker_assoc.id
SET exp_credit_tracker_assoc.id = exp_credit_tracker_designation.assocaition_id
For me it could be the faster way to populate my brand new table and interact with them.
I'm not sure if it is possible or even if it makes sense.
I will be waiting for a good suggestion about the approach to follow in those cases.
You say you want to update the exp_credit_tracker_designation table with data from another table, even though exp_credit_tracker_designation doesn't have any data in it already, This is not possible with an update statement
Update statements change existing data and since there is no data there already, there is nothing to update, at least thats how I interpret your question.
You will have to use an insert statement to input that data from one table to another if the other has no data already. This is quite simple to accomplish
you can do a statement like this:
insert into table1 (column1, column2, column3)
select column1, column2, column3 from table2
Since you say you are rather new to MySQL you may notice that I did not use the traditional syntax of
Insert into foo (bar, biz, bad)
values (X, Y, Z)
this is because you are pulling data from another table.
I've almost finished a project involving customers and products and only identified at the end that we have duplicate records due to keying errors, where sales staff have added the same customer to the database more than once.
What I need to do is to identify the duplicate records by comparing Customer name and their Postcode and merge the Products so that the resulting updated products field is consistent with all of the products that are applicable to them, but only one customer record exists.
In order to explain this, I have put together a small example.
DROP TABLE IF EXISTS `tblProducts`;
CREATE TABLE `tblProducts` (
`ID` int(10) DEFAULT NULL,
`Customer` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`Postcode` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`Products` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `tblProducts` VALUES ('1', 'Bradford', 'BR1 2HJ', '111&222&444');
INSERT INTO `tblProducts` VALUES ('2', 'Bradford', 'BR1 2HJ', '222');
INSERT INTO `tblProducts` VALUES ('3', 'Tanner', 'TE4 9PO', '777&333');
INSERT INTO `tblProducts` VALUES ('4', 'Smythe', 'SM3 8KO', '111&222');
INSERT INTO `tblProducts` VALUES ('5', 'Francis', 'FL2 6HG', '444&333');
INSERT INTO `tblProducts` VALUES ('6', 'Tanner', 'TE4 9PO', '555');
INSERT INTO `tblProducts` VALUES ('7', 'Peters', 'PE4 4PE', '444');
INSERT INTO `tblProducts` VALUES ('8', 'Jeffrey', 'JE9 4JK', '444&555&888');
INSERT INTO `tblProducts` VALUES ('9', 'Barnes', 'BA5 5AB', '999');
INSERT INTO `tblProducts` VALUES ('10', 'Smythe', 'SM1 4GE', '888&777&222');
If we run the following query, you will see that we have two duplicates, for Bradford and Tanner.
SELECT Customer, Postcode, COUNT(*) FROM tblProducts group by Customer, Postcode having count(*) > 1
Customer Postcode COUNT(*)
Bradford BR1 2HJ 2
Tanner TE4 9PO 2
The separate duplicate records are:
Customer Postcode Products
Bradford BR1 2HJ 111&222&444
Bradford BR1 2HJ 222
Tanner TE4 9PO 777&333
Tanner TE4 9PO 555
I need to run a MySQL query to 'merge products where customer and postcode count > 1' as above, so the end result will be:
Customer Postcode Products
Bradford BR1 2HJ 111&222&444
Tanner TE4 9PO 777&333&555
Note that there is only one instance of 222 in the first record as 222 already existed. The duplicate record will be removed from the MySQL table so that only one record exists.
I must admit, I had assumed this would be easy for MySQL to achieve and have spent ages researched merging rows, merging fields, removing duplicates and not found anything that seems to specifically to help.
Link to jsfiddle if it helps: http://sqlfiddle.com/#!9/966550/4/0
Can anyone help please as I am stuck.
Many thanks,
Rob
SELECT TP.Customer,TP.Postcode,TP.Products
FROM tblProducts TP
INNER JOIN
(
SELECT MIN(ID) ID FROM tblProducts GROUP BY Customer, Postcode
)INNERTABLE ON INNERTABLE.ID=TP.ID
You can try above query.
I just performed 3x the following SQL:
REPLACE INTO `admin_gerschap`.`prices` (`ean`, `shopID`, `price`, `shipmentCost`, `productURL`) VALUES ('12', '1', '3', '11', '5')
This shouldn't create 3 records, right? But it created 3x the same record.
What am I doing wrong?