Union - Same table, excluding previous results MySQL - mysql

I'm trying to write a query that will:
Run a query, give me (x) number of rows (limit 4)
If that query didn't give me the 4 I need, run a second query limit 4-(x) and exclude the ids from the first query
A third query that acts like the second
I have this:
(SELECT *, 1 as SORY_QUERY1 FROM xbamZ where state = 'Minnesota' and industry = 'Miscellaneous' and id != '229' limit 4)
UNION
(SELECT *, 2 FROM xbamZ where state = 'Minnesota' limit 2)
UNION
(SELECT *, 3 FROM xbamZ where industry = 'Miscellaneous' limit 1)
How (or is?) do I do that? Am I close? This query gives me duplicates

I think there is no need for union and three selects. One will work as well
SELECT a.*
FROM
(
SELECT xbamZ.*,
CASE
WHEN state = 'Minnesota' and industry = 'Miscellaneous' and id != '229' THEN 1
WHEN state = 'Minnesota' THEN 2
WHEN industry = 'Miscellaneous' THEN 3
END as rnk
FROM xbamZ
where state = 'Minnesota' or industry = 'Miscellaneous'
)a
ORDER BY rnk
LIMIT 4;

Related

SQL limiting the output to a number of results

I have this query.
SELECT * FROM Customer WHERE TAGID IN ('UK', 'Germany');
This outputs the results to show all customers in UK and Germany, but as you can imagine, there will be loads of outputs, and I just require it to output 2 results for UK and 2 results for Germany?
Is this possible?
UNION ALL comes to mind:
(SELECT c.*
FROM Customer c
WHERE TAGID = 'UK'
LIMIT 2
) UNION ALL
(SELECT c.*
FROM Customer c
WHERE TAGID = 'Germany'
LIMIT 2
);
Note that this can take advantage of an index onCustomer(TagID). Also, this returns two arbitrary rows. You can use an ORDER BY to return the newest, oldest, biggest, smallest, reddest, bluest or whatever.
Here is a db<>fiddle.
Yes It is possible. Please check below methods.
Method 1 :
SELECT TOP 2 * FROM Customer WHERE TAGID ='UK'
UNION ALL
SELECT TOP 2 * FROM Customer WHERE TAGID = 'Germany'
Method 2:
(SELECT * FROM Customer WHERE TAGID ='UK' LIMIT 2)
UNION ALL
(SELECT * FROM Customer WHERE TAGID = 'Germany' LIMIT 2)
Method 3:
(SELECT * FROM Customer WHERE TAGID ='UK' AND ROWNUM = 2)
UNION ALL
(SELECT * FROM Customer WHERE TAGID = 'Germany' AND ROWNUM = 2)

Random elements inside JOIN

I have this code here
INSERT INTO Directory.CatalogTaxonomy (`CatalogId`, `TaxonomyId`, `TaxonomyTypeId`, `IsApprovalRelevant`)
SELECT cat.CatalogId, dep.Id, #department_type, false
FROM Directory.Catalog cat
JOIN (SELECT * FROM (
SELECT * FROM Taxonomy.Department LIMIT 10
) as dep_tmp ORDER BY RAND() LIMIT 3) AS dep
WHERE cat.CatalogId NOT IN (SELECT CatalogId FROM Directory.CatalogTaxonomy WHERE TaxonomyTypeId = #department_type)
AND cat.UrlStatus = #url_status_green
AND (cat.StatusId = #status_published
OR cat.StatusId = #status_review_required);
And the problem is that, it should for each catalog take the first 10 elements from Department and randomly choose 3 of them, then add to CatalogDepartment 3 rows, each containing the catalog id and a taxonomy id. But instead it randomly chooses 3 Department elements and then adds those 3 elements to each catalog.
The current result looks like this:
1 000de9d7-af8b-4bac-bdbd-e6e361e5bc5e
1 001d4060-2924-4c75-b304-d780454f261b
1 001bc4b8-c1bc-498d-9aee-3825a40587d5
2 000de9d7-af8b-4bac-bdbd-e6e361e5bc5e
2 001d4060-2924-4c75-b304-d780454f261b
2 001bc4b8-c1bc-498d-9aee-3825a40587d5
3 000de9d7-af8b-4bac-bdbd-e6e361e5bc5e
3 001d4060-2924-4c75-b304-d780454f261b
3 001bc4b8-c1bc-498d-9aee-3825a40587d5
As you can see, there are only 3 departments chosen and repeated for every catalog
If you think that the query:
SELECT * FROM (
SELECT * FROM Taxonomy.Department LIMIT 10
) as dep_tmp
ORDER BY RAND() LIMIT 3
that you join to Directory.Catalog returns 3 different departments for each catalog then you are wrong.
This query is executed only once and returns 3 random departments which are joined (always the same 3) to Directory.Catalog.
What you can do is after you CROSS JOIN 10 departments to Directory.Catalog, choose randomly 3 of them for each catalog.
Try this:
INSERT INTO Directory.CatalogTaxonomy (`CatalogId`, `TaxonomyId`, `TaxonomyTypeId`, `IsApprovalRelevant`)
WITH cte AS (
SELECT cat.CatalogId, dep.Id AS TaxonomyId, #department_type AS TaxonomyTypeId, false AS IsApprovalRelevant
FROM Directory.Catalog AS cat
CROSS JOIN (SELECT * FROM Taxonomy.Department LIMIT 10) AS dep
WHERE cat.CatalogId NOT IN (SELECT CatalogId FROM Directory.CatalogTaxonomy WHERE TaxonomyTypeId = department_type)
AND cat.UrlStatus = #url_status_green
AND (cat.StatusId = #status_published OR cat.StatusId = #status_review_required);
)
SELECT t.CatalogId, t.TaxonomyId, t.TaxonomyTypeId, t.IsApprovalRelevant
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY CatalogId ORDER BY RAND()) rn
FROM cte
) t
WHERE t.rn <= 3
Note that this:
SELECT * FROM Taxonomy.Department LIMIT 10
does not guarantee that you get the first 10 elements from Department because a table is not ordered.

Calculate count records from mysql group by fields

My table in MySQL
http://joxi.ru/5mdWRV8tyQzyr1
My programm pass array users
$ids = [1, 3, 7];
My query for table:
SELECT responsible_id, count(id) as count
from test
WHERE active = 1
AND status = 3
AND responsible_id in (1, 3, 7)
GROUP BY responsible_id
ORDER BY count(id)
I get result http://joxi.ru/vAWYGq0IMxdjmW
But, I need also first row with responsible_id = 7 and count = 0 if not exist on table.
To do what you want, use a left join:
SELECT v.responsible_id, count(t.id) as count
FROM (SELECT 1 as responsible_id UNION ALL
SELECT 3 as responsible_id UNION ALL
SELECT 7 as responsible_id
) v LEFT JOIN
test t
ON t.responsible_id = v.responsible_id AND
t.active = 1 AND
t.status = 3
GROUP BY v.responsible_id
ORDER BY count(id);
Note that the conditions in the WHERE have been moved to the ON clause.

Is it possible to combine these 4 queries into one more efficient query?

I am hoping I can perform this with one single query to the database:
// These four variables can change...
$weave = 10;
$grade = 4;
$model = 1;
$brim = 7;
Now I have these 4 queries:
SELECT WeaveDesc FROM store_item_weaves WHERE ID = '$weave' LIMIT 1
SELECT GradeDesc FROM store_item_grades WHERE ID = '$grade' LIMIT 1
SELECT ModelDesc FROM store_item_models WHERE ID = '$model' LIMIT 1
SELECT BrimDesc FROM store_item_brims WHERE ID = '$brim' LIMIT 1
Is it possible to join all of these into one more efficient query?
Try this one:
SELECT
(SELECT WeaveDesc FROM store_item_weaves WHERE ID = '$weave' LIMIT 1) AS WeaveDesc,
(SELECT GradeDesc FROM store_item_grades WHERE ID = '$grade' LIMIT 1) AS GradeDesc,
(SELECT ModelDesc FROM store_item_models WHERE ID = '$model' LIMIT 1) AS ModelDesc,
(SELECT BrimDesc FROM store_item_brims WHERE ID = '$brim' LIMIT 1) AS BrimDesc
You could achieve this with a union query, like the following:
(SELECT WeaveDesc FROM store_item_weaves WHERE ID = '$weave' LIMIT 1)
UNION
(SELECT GradeDesc FROM store_item_grades WHERE ID = '$grade' LIMIT 1)
UNION
(SELECT ModelDesc FROM store_item_models WHERE ID = '$model' LIMIT 1)
UNION
(SELECT BrimDesc FROM store_item_brims WHERE ID = '$brim' LIMIT 1)
The database performance is not going to be significantly faster than running the queries individually, and may in fact be more difficult to manipulate the result set without adding an extra column to your result set.
It also goes without saying that you should follow the best practice of your programming language to use parameterized queries to prevent SQL injection.
If all the queries return the same number of fields and the corresponding fields have similar types and meaning then you can combine the four queries into a single query using UNION:
(SELECT 'weave' AS item, WeaveDesc AS desc FROM store_item_weaves WHERE ID = '$weave' LIMIT 1)
UNION
(SELECT 'grade' AS item, GradeDesc FROM store_item_grades WHERE ID = '$grade' LIMIT 1)
UNION
(SELECT 'model' AS item, ModelDesc FROM store_item_models WHERE ID = '$model' LIMIT 1)
UNION
(SELECT 'brim' AS item, BrimDesc FROM store_item_brims WHERE ID = '$brim' LIMIT 1)
The query retrieves at most 4 rows, at most 1 from each table. Each row has the columns item (use it to know from what table each row was extracted) and desc (the actual value extracted from the table).
It doesn't necessarily run faster that the four individual queries. It only saves the time needed to send three more requests and receive three more result sets.

Using union and then arrange the data with order by from second row onwards

lets i have this query
select * from items where status = 'A' and staffid = '$var1' and workid != '$var2' order by seq asc
and it will result in
1
2
3
4
5
But now i have another query
select * from items where status = 'A' and staffid = '$var1' and workid = '$var2'
UNION
select * from items where status = 'A' and staffid = '$var1' and workid != '$var2' order by seq asc
I would like the second query to return
4
1
2
3
5
The result is that way because the query before the union will return "4" and after that i would love to rearrange the result according to seq ascending. Is there a way to arrange the result of a query based on second or Nth row onwards? Is there such a technique to combine both union and order to get this result? if there isnt , could someone show me another idea. by just using a single query. I know theres and alternative by splitting both query out. I just wanna know in this sense, is it possible. THanks in advance.
select *,1 as tab from items where status = 'A' and staffid = '$var1' and workid = '$var2'
UNION
select *,2 from items where status = 'A' and staffid = '$var1' and workid != '$var2' order by tab,seq