Using laravel/fluent query builder, I'm trying to cause a constant field value to pass through for a union(ed) selection that is subsequently ordered . I haven't found the recipe to do the following with fluent. The unions are easy, but how do you get the field constant to work?
Imagine two simple tables (omitted) and a union select:
select field1, field2, 'type1' as field3 from table1
UNION
select field1, field2, 'type2' as field3 from table2
ORDER BY field2
The best answer I've come up with so far, is to use a DB::query with a query string I manufacture myself. Laravel/fluent does not seem ready to handle this case, given the test cases I've tried. Using RAW for a select works great, until you try to order the pair of selected table queries.
SELECT field1, field2 FROM
(
SELECT fld1A as field1, 'FOO' as field2 from table1
UNION ALL
SELECT fld2A as field1, 'BAR' as field2 from table2
)
temp_table order by somefield
Using Laravel 4, and using GROUP BY, rather than ORDER BY I believe you can do something like:
$t1 = DB::table('table1')
->select('field1',DB::raw("'FOO' as field2"))
->groupBy('field2');
$t2 = DB::table('table2')
->select('field1',DB::raw("'BAR' as field2"))
->groupBy('field2');
$result = $t1->union($t2)->get();
I found that $t1 in this case can be an instance of Illuminate\Database\Query\Builder or Illuminate\Database\Eloquent\Builder, but the union argument ($t2) must be of type Illuminate\Database\Query\Builder.
This means that you may use eager loading with something like:
$t1 = MyTableModel::with('table3')->select...
This way, probably:
$users = DB::table('users')
->select(DB::raw("'FOO' as field2"))
->get();
Related
Before running a REGEXP_REPLACE on a big table, I want to preview the results, so I want to copy the 'before' and 'after' of the modified field to another table so I can audit.
What's the best way to do this?
Something like
INSERT INTO table2 (before, after)
SELECT field1, REGEXP_REPLACE(field1,'foo','bar')
FROM table1
WHERE condition
(MariaDB)
If this were my project I'd do these things.
First. Just do this and eyeball the results.
SELECT COUNT(*), field1, REGEXP_REPLACE(field1,'foo','bar')
FROM table1
WHERE field1 <> REGEXP_REPLACE(field1,'foo','bar')
GROUP BY field1, REGEXP_REPLACE(field1,'foo','bar')
ORDER BY COUNT(*), field1
That will show you the least frequent values first so you can see the one-off problems caused by your replace first. No need to create a table.
Second, I'd eyeball the values that DIDN'T change with this, changing the WHERE clause from <> to =.
SELECT COUNT(*), field1
FROM table1
WHERE field1 = REGEXP_REPLACE(field1,'foo','bar')
GROUP BY field1
ORDER BY COUNT(*), field1
Maybe some stuff didn't change that should have.
Edit SQL can get a little verbose. If you're fiddling around with some complex conversion functions you might try creating a view. Something like this:
CREATE OR REPLACE VIEW testview AS
SELECT field1,
REGEXP_REPLACE(field1,'foo','bar') changed
FROM table1;
Then you can do
SELECT COUNT(*), field1, changed
FROM testview
WHERE field1 <> changed
GROUP BY field1, changed
ORDER BY COUNT(*), field1;
And similar queries. If you must change your replace function, you can edit the view definition and do the CREATE OR REPLACE again.
I get data from MySQL with if statement as code below. but I get an error:
Error Code: 1241. Operand should contain 1 column(s).
so can someone can help me?
I can not put it into the procedure, because I am using spring + mybatis in the project and i will put this code into them.
SELECT IF((SELECT COUNT(*) FROM table1 WHERE someField = 'A') < 0,
(SELECT * FROM table2 WHERE someField = 'A'),
(SELECT * FROM table1 WHERE someField = 'A'))
From the comments: I wanna get data of 1 in 2 tables when table 1 don't have data I will get data from table 2.
That sounds like union all and not exists:
select * from table1 where someField = 'A'
union all
select * from table2 where not exists(select 1 from tabe1 where someField = 'A'
Note that, for this to work, both tables must contain exactly the same number of columns, whith aligned datatypes. You should really be enumerating the columns that you want to show in the resultset in both unioned queries, to avoid any possible ambiguity. If needed, you can cast columns or add litteral values to any or both of the resultset to align the resultsets (without seeing your actual data structures, I cannot tell how to do).
How do I copy content from one table with a where clause to the same table to another where clause?
So the Select Query would be:
SELECT * FROM items WHERE countryNr=5;
I want now to insert all data from the above query into for example countryNr=1.
So countryNr=5 and CountryNr=1 should habe in the end the same data.
What you have described is more like an UPDATE than INSERT...
in that case your query could be something like this:
update item
set (field1, field2) = (select field1, field2 from item where countrNR = 5)
where countrNR = 1
I'm not sure I understand the question but something like... mySQL docs for insert into select
Insert into items Select Field1, Field2, Field3, Field4..., 1 as countryNR
from items where countrNR = 5
I obtain a series of values that appear only one time in my database using COUNT in mysql that list below:
valueName
---------
value1
value2
value3
value4
I need a script that retrieves all records in a table where valueName are not the values listed in the initial count, and I need this two steps to run in a single script (doesn't matter how many parts it has).
I've got the script to obtain the list above like this:
SELECT field AS new_name FROM table GROUP BY field HAVING COUNT(field) = 1;
And it works.
The problem is that I don't know how to work with the aggregated result of the first step. Maybe using some kind of function. Or loop (I don't think in SQL..).
I've tried different things like attaching a COUNT inside a WHERE clause and others but it doesn't work.
Please help!
Use a join:
select t.*
from table t join
(SELECT field
FROM table
GROUP BY field
HAVING COUNT(field) > 1
) filter
on t.field = filter.field;
If you have a primary key in your table and an index on table(field, pk), the following is probably faster:
select t.*
from table t
where exists (select 1
from table t2
where t2.field = t.field and t2.pk <> t.pk
);
Try this:
SELECT table.* FROM table
JOIN
(SELECT field FROM table GROUP BY field HAVING COUNT(field) > 1) newtable
ON
table.field = newtable.field;
This should work.
suppose I do this:
SELECT * FROM table WHERE field2 = '2019#162440' OR field2 LIKE '%%2019#%%';
In this case, it will try to execute the matching of BOTH field2 = '2019#162440'and field2 LIKE '%%2019#%%' conditions (ie, it will search for rows matching those conditions hence it takes some more computation power to try to find rows matching both condition even if it already found a row matching field2 = '2019#162440')
Is there a way to instruct mysql by reforming the query to ONLY try to execute field2 LIKE '%%2019#%%' if the condition field2 = '2019#162440' does not match anything so that the query becomes more efficient
IE. I essentially want mysql to only try to find rows matching field2 LIKE '%%2019#%%' only if no rows match field2 = '2019#162440'. If a row that matches field2 = '2019#162440' is found, do NOT try to match field2 LIKE '%%2019#%%'
Also, no subqueries
Let me start by stating that I am not an expert in MySQL. It is not nearly as optimized as some other DBMSes, so the following query might not actually reduce your execution time. But it's worth a shot...
If field2 is indexed, this might be a really fast solution:
-- Get results where field2 = '2019#162440'
SELECT *
FROM table
WHERE field2 = '2019#162440'
-- Append...
UNION
-- Get results where field2 LIKE '%%2019#%%' but only
-- if there are no rows where field2 = '2019#162440'
SELECT *
FROM table
WHERE NOT EXISTS(
SELECT *
FROM table
WHERE field2 = '2019#162440'
)
AND field2 LIKE '%%2019#%%'
You are going to run your fastest query and select all results. Then, append the second, slower query which contains an EXISTS. The EXISTS clause will return true if the subquery contains any rows, which should short-circuit the entire second query and prevent it from runnning (thus appending 0 rows). If the first query returns 0 rows, however, then the second query will kick in and run the slower LIKE comparisons.
The best I can do is use the FOUND_ROWS() function along with a UNION:
SELECT *
FROM t
WHERE field2 = '2019#162440'
UNION ALL
SELECT *
FROM t
WHERE FOUND_ROWS() = 0
AND field2 LIKE '%%2019#%%'
SQL Fiddle Demo