Mysql remove duplicate from a row and update the row - mysql

I have a mysql table like
+-----------------+---------------------------------------------------------------+---------+
| col_key |member_column | weight |
+-----------------+---------------------------------------------------------------+---------+
| 4:20131205:0922 | 018210020504;4.1672|018210020504;4.1672 | 8.3344 |
| 4:20131204:0923 | 015819070006;13.8584|015819070006;13.8584 | 27.7168 |
| 4:20131202:0922 | 018710040303;8.7864 | 8.7864 |
| 4:20131204:0923 | 017319010003;2.7044|017319010004;2.7044 | 5.4088 |
| 4:20131202:0922 | 055320020104;7.3357 | 7.3357 |
| 4:20131217:0922 | 019120020404;7.8727|019120020404;7.8727 | 15.7454 |
| 4:20131223:0923 | 011820010203;11.5213 | 11.5213 |
| 4:20131216:0925 | 018320010403;13.7416 | 13.7416 |
| 4:20131217:0922 | 017420020205;6.7384 | 6.7384 |
| 4:20131217:0922 | 019723010104;4.3660|050122010004;12.1407|050122010003;12.1407 | 28.6474 |
| 4:20131224:0926 | 022923040107;10.2461|022923040106;10.2461 | 20.4922 |
| 4:20131216:0925 | 050122010004;12.1407|050122010003;12.1407 | 24.2814 |
| 4:20131216:0925 | 061020030007;3.8048 | 3.8048 |
+-----------------+---------------------------------------------------------------+---------+
Here member_columns has values different member:weight which is | separated. Weight columns has total weight for the member in a particular row.
We need to remove duplicate members from the member_columns and update the weight correspondingly.
Example:
row with col_key 4:20131205:0922 has member_column in which members are repeated .
I need this columns updated to
4:20131205:0922 | 018210020504;4.1672 | 4.1672
Similarly for the column
4:20131217:0922 | 019723010104;4.3660|050122010004;12.1407|050122010003;12.1407|28.6474
I need it to be updated as
4:20131217:0922 | 019723010104;4.3660|050122010004;12.1407|16.5067
I was looking towards cursor for the solution but learn that cursor do not update the actual data.
Please HELP .

For this approach, you will need to take help from any server side script. So the Process to follow would be
1) select all rows having member_column as your resultset field from the table narrowing down by any condition of your choice
2) Iterate the result set
3) Explode the member_column field by "|" and form an array of strings. which would come as
array("4:20131217:0922", "019723010104;4.3660","050122010004;12.1407","16.5067");
4) Do all your computation and remove duplicates
5) once you have a unique array, implode it back with dash "|"
6) update the row back.
Hope it helps :)

Related

MySQL - Interchange column value from one row onto another

SELECT OlineDate, OlineOrder, OlineDesc, OlineGroup, OlinePrice
FROM tblorderlines
WHERE DATE(OlineDate) = '2019-10-19' AND OlineOrder = 170
AND OlineGroup IN ('spec')
|====================================================================|
| OlineOrder |OlineDate | OlineDesc | OlineGroup | OlinePrice |
|============+============+===========+================+=============|
| 10 | 2019-10-19 | Coupon | spec | -2.42 |
|------------+------------+-----------+----------------|-------------|
| 10 | 2019-10-19 | 10% OFF | spec | 0.00 |
|------------+------------------------+----------------+-------------|
I am looking for a query that would interchange the '10% off' value over the 'Coupon' value. The only results I've found that may produce the result I want are pivot tables but those don't exist in MySQL. Is there another route I can take?

When inserting new record in existing table tt goes up instead of down

I have already created table I want to add extra row when adding extra row the created extra row goes up. I want that row at the bottom.
MariaDB [armydetails]> insert into armydetails values('r05','Shishir','Bhujel','Jhapa','9845678954','male','1978-6-7','1994-1-3','ran5','Na11088905433');
Query OK, 1 row affected (0.17 sec)
MariaDB [armydetails]> select * from armydetails;
+-------+---------+---------+-----------+------------+--------+------------+------------+--------+----------------+
| regNo | fName | lName | address | number | gender | DOB | DOJ | rankID | accountNo |
+-------+---------+---------+-----------+------------+--------+------------+------------+--------+----------------+
| r05 | Shishir | Bhujel | Jhapa | 9845678954 | male | 1978-06-07 | 1994-01-03 | ran5 | Na11088905433 |
| ro1 | Milan | Katwal | Dharan | 9811095122 | Male | 1970-01-03 | 1990-01-01 | ran1 | Na11984567823 |
| ro2 | Hari | Yadav | Kathmandu | 9810756436 | male | 1980-06-07 | 2000-05-06 | ran2 | Na119876678543 |
| ro3 | Khrisna | Neupane | Itahari | 9864578934 | male | 1980-02-02 | 2001-01-07 | ran3 | Na11954437890 |
| ro4 | Lalit | Rai | Damak | 9842376547 | male | 1989-05-09 | 2005-01-02 | ran4 | Na11064553221 |
+-------+---------+---------+-----------+------------+--------+------------+------------+--------+----------------+
5 rows in set (0.00 sec)
MariaDB [armydetails]>
The SQL 2011 publication from ISO/IEC 9075 says:
In general, rows in a table are unordered; however, rows in a table are ordered if the table is the result of a that immediately contains an « order by clause ».
In a SQL database, there is no underlying, default ordering for records. A relational database basically stores a table as a bunch of unordered records.
When records are SELECTed without an ORDER BY clause, they come out in an undefined order, that in no way is guaranteed to be consistent over subsequent queries (including the very same query being executed several times). This is true for MySQL and for other RDBMS.
The only way to properly order records is to use an ORDER BY clause, like:
select * from armydetails order by regNo
Suggested lecture: Tom Kyte Blog : Order in the Court!.
You can simply add an ORDER BY clause to your statment as follows:
SELECT * FROM armydetails ORDER BY regNO DESC;

Select value from table sorted by a certain order from another table

I want to select value from table sorted by a certain order.
I have a table called test that looks like this:
| date | code | value |
+----------+-----------+----------+
| 20050104 | 000005.SZ | -6359.19 |
| 20050104 | 600601.SH | -7876.34 |
| 20050104 | 600602.SH | -25693.3 |
| 20050104 | 600651.SH | NULL |
| 20050104 | 600652.SH | -15309.9 |
...
| 20050105 | 000005.SZ | -4276.28 |
| 20050105 | 600601.SH | -3214.56 |
...
| 20170405 | 000005.SZ | 23978.13 |
| 20170405 | 600601.SH | 32212.54 |
Right now I want to select only one date, say date = 20050104, and then sort the data by a certain order (the order that each stock was listed in the stock market).
I have another table called stock_code which stores the correct order:
+---------+-----------+
| code_id | code |
+---------+-----------+
| 1 | 000002.SZ |
| 2 | 000004.SZ |
| 3 | 600656.SH |
| 4 | 600651.SH |
| 5 | 600652.SH |
| 6 | 600653.SH |
| 7 | 600654.SH |
| 8 | 600602.SH |
| 9 | 600601.SH |
| 10 | 000005.SZ |
...
I want to sorted the selected data by stock_code(code_id), but I don't want to use join because it takes too much time. Any thoughts?
I tried to use field but it gives me an error, please tell me how to correct it or give me an even better idea.
select * from test
where date = 20050104 and code in (select code from stock_code order by code)
order by field(code, (select code from stock_code order by code));
Error Code: 1242. Subquery returns more than 1 row
You told us that you don't want to join because it takes too much time, but the following join query is probably the best option here:
SELECT t.*
FROM test t
INNER JOIN stock_code sc
ON t.code = sc.code
WHERE t.date = '20050104'
ORDER BY sc.code_id
If this really runs slowly, then you should check to make sure you have indices setup on the appropriate columns. In this case, indices on the code columns from both tables as well as an index on test.date should be very helpful.
ALTER TABLE test ADD INDEX code_idx (code)
ALTER TABLE test ADD INDEX date_idx (date)
ALTER TABLE code ADD INDEX code_idx (code)

check if row has a particular value (perl,mysql)

I'm trying to identify if a row has the value '1' anywhere in it (AKA any column). Is there an easy way to do this without searching every column with fetchrow_array? I've included a small table I've been working with as an example.
mysql> select * from Case_Tracking;
+--------------------+---------+---------+----------+---------+----------+---------------+
| accession_number | cyp2d6 | cyp2c19 | factorII | factorV | apoe | vkorc1_cyp2c9 |
+--------------------+---------+---------+----------+---------+----------+---------------+
| AIB14-1116-0000453 | Luminex | Luminex | Hologic | 1 | ABI 7500 | Genmark |
| AIB14-1123-0000074 | NULL | Luminex | Hologic | Hologic | ABI 7500 | Genmark |
+--------------------+---------+---------+----------+---------+----------+---------------+
It would be better to search every column using SQL (WHERE accession_number = '1' OR cyp2d6 = '1' OR ...) since you'd only need to fetch matching results.

Table has pairs of matching records, need to select and update only one record

I have a table with pairs of matching records that I query like this:
select id,name,amount,type from accounting_entries
where name like "%05" and amount != 0 order by name limit 10;
Results:
+------+----------------------+--------+-------+
| id | name | amount | type |
+------+----------------------+--------+-------+
| 786 | D-1194-838HELLUJP-05 | -5800 | DEBIT |
| 785 | D-1194-838HELLUJP-05 | -5800 | DEBIT |
| 5060 | D-1195-UOK4HS5POF-05 | -5000 | DEBIT |
| 5059 | D-1195-UOK4HS5POF-05 | -5000 | DEBIT |
| 246 | D-1196-0FUCJI66BX-05 | -7000 | DEBIT |
| 245 | D-1196-0FUCJI66BX-05 | -7000 | DEBIT |
| 9720 | D-1197-W2J0EC1BOB-05 | -6500 | DEBIT |
| 9719 | D-1197-W2J0EC1BOB-05 | -6500 | DEBIT |
| 2694 | D-1198-MFKIKHGW0S-05 | -5500 | DEBIT |
| 2693 | D-1198-MFKIKHGW0S-05 | -5500 | DEBIT |
+------+----------------------+--------+-------+
10 rows in set (0.01 sec)
I need to perform an update so that the resulting data will look like this:
+------+----------------------+--------+--------+
| id | name | amount | type |
+------+----------------------+--------+--------+
| 786 | D-1194-838HELLUJP-05 | -5800 | DEBIT |
| 785 | C-1194-838HELLUJP-05 | 5800 | CREDIT |
| 5060 | D-1195-UOK4HS5POF-05 | -5000 | DEBIT |
| 5059 | C-1195-UOK4HS5POF-05 | 5000 | CREDIT |
| 246 | D-1196-0FUCJI66BX-05 | -7000 | DEBIT |
| 245 | C-1196-0FUCJI66BX-05 | 7000 | CREDIT |
| 9720 | D-1197-W2J0EC1BOB-05 | -6500 | DEBIT |
| 9719 | C-1197-W2J0EC1BOB-05 | 6500 | CREDIT |
| 2694 | D-1198-MFKIKHGW0S-05 | -5500 | DEBIT |
| 2693 | C-1198-MFKIKHGW0S-05 | 5500 | CREDIT |
+------+----------------------+--------+--------+
10 rows in set (0.01 sec)
One entry should negate the other entry. It doesn't matter if I update the first or second matching record, what matters is that one has a positive amount and the other has a negative amount. And the type and name need to be updated.
Any clues on how to do this? What would the update command look like? Maybe using a group by clause? I have some ideas on how to do it with a stored procedure, but can I do it with a simple update?
Try this:
UPDATE accounting_entries as ae
SET name = 'C' + SubString(name, 1, Length(name) - 1))
amount = amount * -1
type = 'Credit'
WHERE id =
(SELECT MIN(id) FROM
(SELECT * FROM accounting_entries) as temp
GROUP BY name)
The key is the subquery in the WHERE section that limits the updates to the lowest ID of each name value. The assumption is that the lower ID is the one that you will always want to update. If this is not correct, then update the subquery based on whatever rule you would use.
Edit: Update to subquery based on technique found here, due to limitation on mysql defined here.
This query gives a method for updating all records at once (as it seemed like this is what the OP was looking for. However, the most efficient way to do this would be to enumerate through all records in code (php, asp.net, etc), and through code-based methods update the rows that needed to change. This would eliminate the performance issues inherent with running updates off of subqueries in mysql.
If the ID:s for a pair always match the formula x and x+1, you could say something like
WHERE MOD(`id`, 2) = 1
EDIT: I haven't tested this code, so I can't guarantee that it's possible to put a column name into a MOD like this, but it might be worth a try, and/or further investigation.
Does this constraint hold true all the time (D == -C) ?
If so, you do not need to keep redundant data in your table, store only one "amount" value (for example the debit):
786 | 1194-838HELLUJP-05 | -5800
and then, on the application level, append a D- to the name and get the raw amount or append a C- and get the - amount.