I've got some sort of static table like:
SELECT * FROM targets;
name | target
name1 | 6
name2 | 3
name3 | 2
and another table with the actual records inside, that I want to measure:
SELECT * FROM records;
id | name | created_on
546 | name1 | 2022-06-02
547 | name2 | 2022-06-04
548 | name2 | 2022-06-07
Now I'd like to build a table, that groups / counts the records per name (per month).
The group by is easy (except the 0 values):
SELECT "name", COUNT("id") FROM "records"
WHERE MONTH("created_on") = MONTH(CURRENT_DATE())
AND YEAR("created_on") = YEAR(CURRENT_DATE())
GROUP BY "name"
But how do I join both tables to get a result like this?
name | target | current
name1 | 6 | 1
name2 | 3 | 2
name3 | 3 | 0
your data
CREATE TABLE targets(
name VARCHAR(70) NOT NULL
,target INTEGER NOT NULL
);
INSERT INTO targets
(name,target) VALUES
('name1',6),
('name2',3),
('name3',2);
CREATE TABLE records(
id INTEGER NOT NULL
,name VARCHAR(70) NOT NULL
,created_on DATE NOT NULL
);
INSERT INTO records
(id,name,created_on) VALUES
(546,'name1','2022-06-02'),
(547,'name2','2022-06-04'),
(548,'name2','2022-06-07');
you should use Join(Left or Right) to include all values including null values and IF logical operator and Subquery to act as table for your query
SELECT targets.name,
target,
IF(current IS NULL, 0, current) AS current
FROM targets
LEFT JOIN (SELECT name,
Count(id) current
FROM records
WHERE Month(created_on) = Month(CURRENT_DATE())
AND Year(created_on) = Year(CURRENT_DATE())
GROUP BY name) records
ON records.name = targets.name
dbfiddle
Related
I need to retrieve rows that have a numeric or null value in the HomeID column and finally return the value with a numeric value if there is a row with the same symbol
// my table
+--------+---------+-------+
| Symbol | Home ID | Value |
+--------+---------+-------+
| test | 1 | value |
| test | NULL | value |
| test1 | 2 | value |
| test2 | 3 | vlaue |
+--------+---------+-------+
Actually, I did something like that. It added up the symbols for me, but I don't know how to return the poem I need
SELECT
[Symbol],
COUNT(*) AS CNT
FROM [DB].[dbo].[Table]
GROUP BY
[Symbol]
HAVING COUNT(*) > 1;
One method is:
select t.*
from t
where t.homeid is not null or
not exists (select 1
from t t2
where t2.symbol = t.symbol and t2.homeid is not null
);
You can also do this with aggregation, if you just have these three columns and you want exactly one row per symbol:
select symbol, max(homeid) as homeid,
coalesce(max(case when homeid is not null then value end),
max(value)
) as value
from t
group by symbol;
I have 3 tables
User Info
id
name
1
bob
2
jane
3
tom
Locations
id
name
1
Test1
2
Test2
3
Test3
4
Test4
User Locations
userID
locationID
1
1
1
2
2
3
Basically What I am trying to achieve is to pull the location names where the user doesn't have it bound already.
In the above list Bob has 2 locations bounded "test 1" and "test 2" but he doesn't have "test 3" or "test 4" yet. I Only want the data to return test 3 and 4 since those are the only ones Bob doesn't have.
For Jane She only has Test 3 bounded but none of the remaining 3
Originally I had tried this and it somewhat worked. However Every time another user gets an unbounded location the its removed from the list. I'm not sure how I would add the user ID in all this so it's only specific to that user.
SELECT `name` FROM `locations`
WHERE `id` NOT IN (SELECT `locationID` FROM `user_locations`)
Create a cartesain product of the user and locations table (cross join), then using an outer join allows us to find rows that are as yet unmatched in user_locations:
select
user_info.ID AS UserID
, locations.ID AS locationID
from user_info
cross join locations
left outer join user_locations on user_info.id = user_locations.userid
and locations.id = user_locations.locationid
where user_locations.userid IS NULL
and user_info.name = 'bob'
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE user_info(
id INTEGER NOT NULL PRIMARY KEY
,name VARCHAR(4) NOT NULL
);
INSERT INTO user_info(id,name) VALUES (1,'bob');
INSERT INTO user_info(id,name) VALUES (2,'jane');
INSERT INTO user_info(id,name) VALUES (3,'tom');
CREATE TABLE locations(
id INTEGER NOT NULL PRIMARY KEY
,name VARCHAR(5) NOT NULL
);
INSERT INTO locations(id,name) VALUES (1,'Test1');
INSERT INTO locations(id,name) VALUES (2,'Test2');
INSERT INTO locations(id,name) VALUES (3,'Test3');
INSERT INTO locations(id,name) VALUES (4,'Test4');
CREATE TABLE user_locations(
userID INTEGER NOT NULL
,locationID INTEGER NOT NULL
);
INSERT INTO user_locations(userID,locationID) VALUES (1,1);
INSERT INTO user_locations(userID,locationID) VALUES (1,2);
INSERT INTO user_locations(userID,locationID) VALUES (2,3);
Query 1:
select
user_info.ID AS UserID
, locations.ID AS locationID
from user_info
cross join locations
left outer join user_locations on user_info.id = user_locations.userid
and locations.id = user_locations.locationid
where user_locations.userid IS NULL
order by 1,2
Results:
| UserID | locationID |
|--------|------------|
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 2 |
| 2 | 4 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
I want to get the last activity of my client but i dont know how to that that with two tables that have more than one pivot. Please look at to the example below :
table product
--------------------------------------------------------------------------------------------------------------------------------------
id | name | check_mo (Activity1) | check_mo_account_id | check_pa (Activity2) | check_pa_account_id
--------------------------------------------------------------------------------------------------------------------------------------------
1 | product1 | 01/02/2020 | 63 | 05/02/2020 | 100
2 | product2 | 01/03/2020 | 23 | 10/03/2020 | 63
-----------------------------------------------------------------------------------------------------------------------------------
Table account
--------------------------------
id | name
--------------------------------
23 | name1
63 | name2
100 | name3
--------------------------------
I want this result (last activity is the lastest date of (check_mo and check_pa). and relationship between tables is (account.id => product.check_mo_account_id and product.check_pa_account_id))
------------------------------------------------
id | name | last activity
-------------------------------------------------
23 | name1 | 01/03/2020
63 | name2 | 10/03/2020
100 | name3 | 05/02/2020
-------------------------------------------------
Unpivot the columns. In MySQL, you can use union all. Use join to bring in the names and then a window function to get the most recent date:
select pn.*
from (select pn.*, max(dte) over (partition by name) as max_dte
from ((select n.name, p.check_mo as dte, p.check_mo_account_id as account_id
from product p join
name n
on p.check_mo_account_id = n.id
) union all
(select n.name, p.check_pa, p.check_pa_account_id as account_id, p.check_pa
from product p join
name n
on p.check_mo_account_id = n.id
)
) pn
) pn
where dte = max_dte;
If I understand correctly, you have two check IDs and two check dates in one row, but want to treat them equally, just as if you had just one table with one check ID and one check date per row. Use UNION ALL to get this table. Then find the maximum date per ID and join this to the account table.
select id, account.name, aggregated.last_activity
from account
join
(
select id, max(check) as last_activity
from
(
select check_mo_account_id as id, check_mo as check from product
union all
select check_pa_account_id as id, check_pa as check from product
) unioned
group by id
) aggregated using (id)
order by id;
Trying to formulate my question as good as I can...
I have a pricing table with historic data in it. So per item there is a price for certain dates. The difficulty is that the rows also have a type (1 = price for purchase order, 2 = sales order) and a VendorID.
That VendorID can be filled on a row: the price on that row is then for that specific vendor. If there is no row for a certain item in this table that has a VendorID, but it does have a row where VendorID is null, that row should be in the result.
So, if there are two rows in the result, one with a VendorID value and one with the VendorID being null, the row with the value should be in the result set and the row with the null value may not be in the result set.
Also, the result set should only contain the prices that are the newest, so i have to take in account the 'FromDate'.
The name of the column 'VendorID' is not well chosen because the rows with type = 2 are for sales orders, but let's forget about that for now ;-)
If I want all items for type = 1, would like to have the following result set:
ID | ItemID | FromDate | Type | VendorID | price
------------------------------------------------
1 | 1. | 2020-01-01 | 1 | 97 | 2.45
9 | 2 | 2020-02-15 | 1 | 97 | 3.88
7 | 3 | 2020-01-01 | 1 | 97 | 2.55
Suppose IDs 3,4 and 9 wheren't in the table (so, no pricing for item 2 for specific VendorID 97), the result should be:
ID | ItemID | FromDate | Type | VendorID | price
------------------------------------------------
1 | 1 | 2020-01-01 | 1 | 97 | 2.45
13 | 2 | 2020-01-01 | 1 | NULL | 999.45
7 | 3 | 2020-01-01 | 1 | 97 | 2.55
For ItemID 2 this would mean that there isn't a specific price set for VendorID 97 but there is a general price set (VendorID is null) and this price should now be placed in the result set.
I hope I explained it more clearly now....
I've written loads of queries now and also googled a lot but I cannot find how to make it do what I want. I tried distinct, sorting, but no luck. Must be something simple but I can't find it.
Up until now I have the following Mysql query but a) it outputs both the rows where VendorID is null and where it has value and b) I think its very overcomplicated but can't figure out how to make it simpler and faster.
SELECT I.ItemID, I.Name, b.vendorID, b.max_date, IP.Price, T.Percentage
FROM Items I
JOIN
(
SELECT ItemID, VendorID, MAX(FromDate) max_date, type
FROM ItemPrices
WHERE
Type = 1 AND
FromDate < '2020-02-30' AND
VendorID = (SELECT ID FROM Vendors WHERE VendorID = 'V001') OR VendorID IS NULL
GROUP BY ItemID, VendorID
) b ON I.ID = b.ItemID
JOIN ItemPrices IP ON IP.ItemID = b.ItemID AND IP.Type = b.type AND IP.FromDate = b.max_date AND (IP.VendorID = b.VendorID OR IP.VendorID IS NULL)
LEFT JOIN TaxCodes T ON T.ID =
(
SELECT TC.TaxCodeID FROM TaxCombinations TC
WHERE
TC.Direction = 1 AND
TC.TaxAreaID = (SELECT TaxArea FROM Vendors WHERE ID = (SELECT ID FROM Vendors WHERE VendorID = 'V001') )
AND TC.ItemTaxID = I.ItemTaxID
)
ORDER BY I.ItemID ASC
Also looked at the following urls but still don't know what to do:
Distinct rows with non-null values taking precedence over nulls
Select the non-null value if exists else null, but always select the row
Can someone please help me?
With NOT EXISTS:
select t.* from tablename t
where t.vendorid is not null
or not exists (
select 1 from tablename
where itemid = t.itemid and vendorid is not null
)
See the demo.
I have two temp table: temp1 and temp 2.
temp 1 is
Reg Key | Player Name | Age
----------------------------
1 | Null | Null
2 | Null | Null
3 | Null | Null
temp 2 is
Reg Key | Question Name | value
----------------------------
1 | Player Name | Ronaldo
2 | Player Name | Zedan
1 | Age | 35
2 | Age | 38
in temp 1 the column name is dynamic except for [Reg Key], for example I need to update the row with [Reg Key] 1 in temp 1 with 'Ronaldo' and 35 from the table temp 2.
I used to loop to get the values from temp 2 and update temp 1, but the records in the table temp 2 now exceed 5 thousand, so I'm trying to create an UPDATE query, but I don't know how to get the columns name at run time.
It sounds like pivot might do the trick:
select 1 as regkey, 'Player Name' as Question_name, 'Ronaldo' as value into #temp2
union all select 2, 'Player Name', 'Zedan'
union all select 1, 'Age', '35'
union all select 2, 'Age', '38'
Select
regkey
, [Player Name]
, [Age]
From #temp2
Pivot (max(value) for Question_Name in ([Player Name], [Age])) as pvt