In my users table I have a field hours, and when I'm selecting all my users I need to also get a variable fullTime which will be based on if hours equals 7.4. Is this something I can do in a query rather than having to loop through all the users? I have 600+ rows and I'm trying to do this the most efficient way as this happens on every page load. I was thinking something like SELECT *, fullTime as (hours EQUALS 7.4) FROM users
EDIT: Working SQL SELECT * , IF(hours_per_day = 7.5, 1, 0) AS fullTime FROM users
The following will return a column with fulltime = 1 if hours = 7.4 and fulltime = 0 otherwise.
SELECT *, IF(hours = 7.4, 1, 0) AS fulltime FROM users
Note that this may fail if hours is a float column due to inaccuracies in floating point numbers.
try this
SELECT * , if(hours >= 7.4 ,col_time, hours) as fullTime FROM users
explanation :
if hours >=7.4 (not only exactly hours=7.4 but also greater.) you will get your column where you stored the full date with time or whole time. you can even change it by DATE_FORMAT. otherwise you will get the hours lets say 5 ,or something.
Related
I am trying to sort my ACCT tags by 30 second intervals between this date range, and my IT tags by 1 minute intervals so that the tags show up in the query results on every 30 seconds and 1 minute.
Right now I have it set to display every one minute, which should work, but because of the group by I need to have some type of aggregate for it before grouping.
SELECT TOP (1000) FactoryTable.[DateAndTime]
,FactoryTable.[OwnerId]
,FactoryTable.[Val]
,FactoryTable.[Status]
,TagsTable.[Tag]
,TagsTable.[TagType]
FROM [DataTable].[dbo].[FactoryTable] as FactoryTable
JOIN [DataTable].[dbo].[TagsTable] as TagsTable
on FactoryTable.[OwnerId] = TagsTable.[OwnerId]
WHERE (TagsTable.[Tag] = '[tag]ACCT156'
OR TagsTable.[Tag] = '[tag]ACCT132'
OR TagsTable.[Tag] = '[tag]ACCT132'
OR TagsTable.[Tag] = '[tag]IT530'
OR TagsTable.[Tag] = '[tag]IT530')
AND FactoryTable.[DateAndTime] >= '2022-11-01 12:30:30.000'
AND FactoryTable.[DateAndTime] < '2022-11-02'
Group BY DATE_BUCKET(minute, FactoryTable.[DateAndTime], FactoryTable.[DateAndTime])/ 1
#1I have tried looking at various discussion posts for this but the queries are much simpler and not as in depth, and I have been having a hard time experimenting successfully what they are doing.
#2 I have tried to do:
SET sql_mode=(SELECT REPLACE(##sql_mode, 'ONLY_FULL_GROUP_BY', ''));
For the group by, but am unable to run this in sql2018 and do not have CLI access. This is posted in another stack overflow article.
I have also tried multiple group bys, using DatePart, etc..
Any help is much appreciated.
I am making a covid log db for easy contact tracing.
these are my tables
log_tbl (fk_UserID, fk_EstID, log_date, log_time)
est_tbl (EstID, EstName)
user_tbl (User_ID, Name, Address, MobileNumber)
I wanted to write a statement that shows when and where an individual (User_ID)
enters an Establishment (EstID),
SELECT l.*
FROM log_tbl l
WHERE (l.EstID, l.log_date) IN (SELECT l2.EstID, l2.log_date
FROM log_tbl l2
WHERE l2.User_ID = 'LIN78JFF5WG'
);
[Result of Query]1
this currently works,
but it still has to be filterd by +-2 hours based on the time the when User_ID was logged on log_tbl, so that it would narrow down result when first query would spit out 1000 logs. Because these Results will be Contacted, and to reduce Costs, it needs to be narrowed down to less than 50%.
So, table below should not include first 2 and last one because it doesn't fit with 1, the date, and 2 the time, in relation to the searched userLIN78JFF5WG
[Unfiltered Result]2
FROM log_tbl
WHERE User_ID = 'LIN78JFF5WG'
AND (BETWEEN subtime(log_tbl.log_time, '02:00:00') AND addtime(log_tbl.log_time, '02:00:00'
I know this is wrong, but I don't have any idea how to join the two queries
and result should include
EstID, Name, Address, MobileNumber, log_date, log_time sorted by Date
Imagine it like this,
There are 3 baskets full of tomatoes,
2 of the baskets have rotten tomatoes inside.
Do you throw away the whole basket full of tomatoes?
No.. you select the rotten tomato, and others close to it, and throw them away.
I need that for the DB, instead of Getting Result for the Whole Day,
I only need the People who are in close contact with The Target user.
is it possible to do this on mysql? I have to use mysql because of reasons..
Here I include the data sample fiddle:
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=050b2103d3adf5828524f49066c12e74
MySQL supports window functions with the range window frame specification. I would suggest:
select l.*
from (select l.*,
sum(case when fk_UserID = 'LIN78JFF5WG' then 1 else 0 end) over
(partition by log_date
order by log_time
range between interval 2 hour preceding and interval 2 hour following
) as cnt_user
from log_tbl l
) l
where cnt_user > 0;
Here is a db<>fiddle.
You can then annotate the results would other columns from other tables to get your final result.
This should be much faster than alternative methods.
Note, however, that you have a flaw in this logic, because it is not checking four hours between 0:00-2:00 a.m. and 22:00-0:00. You can store the date/time in a single column to make it easier to get a more accurate list.
I am not fully understand your requirements.
but I write sample sql so that we can make it clear
select *,(select UNIX_TIMESTAMP(CONCAT(log_date," ",log_time)) as ts from log_tbl where fk_UserID='LIN78JFF5WG') as target_time
from
log_tbl as l
-- simple join query.to get intend information
left join user_tbl as u on (u.User_id=l.fk_UserID)
left join est_tbl as e on (l.fk_EstID=e.EstID)
-- mysql datediff only return day as unit.so we convert to timestamp to do the diff
where UNIX_TIMESTAMP(CONCAT(l.log_date," ",l.log_time)) - target_time between 60*60*2 and 60*60*2
-- solution two
-- but I suggest you divide it into two sql like this.
select UNIX_TIMESTAMP(CONCAT(log_date," ",log_time)) as ts from log_tbl where fk_UserID='LIN78JFF5WG';
-- we get the user log timestamp.and use it in next query
select *
from
log_tbl as l
-- simple join query.to get intend information
left join user_tbl as u on (u.User_id=l.fk_UserID)
left join est_tbl as e on (l.fk_EstID=e.EstID)
-- mysql datediff only return day as unit.so we convert to timestamp to do the diff
where UNIX_TIMESTAMP(CONCAT(l.log_date," ",l.log_time)) - [target_time(passed by code)] between 60*60*2 and 60*60*2
I am trying to do a select from CTE based on a condition.
There is a variable I've declared for today's period (#PRD). It holds the value of what period we are currently in.
Now I would like to do a selection from a table that will restrict what information is returned based on whether we are in the first half of the year or not.
For instance, we are in period 2 so I want everything returned from my CTE which falls between PRD 1 and 5. IF we were in say period 6 (after 5), then yes I'd want everything returned from the table.
This is the pseudocode of what I'm trying to accomplish:
SELECT
CASE
WHEN #PRD <= 5
THEN (SELECT * FROM DISPLAY WHERE PERIOD IN (1,2,3,4,5))
ELSE (SELECT * FROM DISPLAY)
END
I'm getting an error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
Please any thoughts on how I can do this?
Thanks x
EDITED/UPDATED:
More of the code involves a CTE and is really long. Bottom line is lets say I have this CTE
;WITH DISPLAY as (
select * from lots_of_things
)
SELECT * FROM DISPLAY
Having done a regular select on this CTE, it returns data that looks like this:
PERIOD (INT) DEPARTMENT GROUP BUDGET
1 ENERGY HE 500
2 ENERGY HE 780
3 ENERGY HE 1500
4 ENERGY HE 4500
5 ENERGY HE 400
6 ENERGY HE 3500
7 ENERGY HE 940
8 ENERGY HE 1200
I want it to show me just the top 5 rows if we the current period is 1,2,3,4,5. But to display ALL table rows if we are in any other period like 6,7,8,9 and onwards. The current period is held in the variable #PRD which is derived from doing a comparison of today's date with ranges held in a table. The value is accurate and also type INT
Hope this helps
SQL FIDDLE
This will work:
SELECT * FROM DISPLAY WHERE (#PRD > 5 OR PERIOD IN (1, 2, 3, 4, 5))
If this code confuses you, what's happening is that we check if #PRD > 5 and if that returns true, our expression is always true so we return all the rows.
If the variable is less or equal to 5 (like you checked in your example), the first check is false and then we check if the period is the list.
This might be a solution:
IF #PRD <= 5
SELECT * FROM DISPLAY WHERE PERIOD IN (1,2,3,4,5)
ELSE
SELECT * FROM DISPLAY
UPD
In this case you should use variable instead of CTE, if it's possible.
DECLARE #PRD INT;
SELECT #PRD = PERIOD FROM SOME_TABLE WHERE ...
I have a $wpdb query I'm trying to execute, but it's not going through and is throwing no error:
$followups =
$wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM orders
WHERE status_id = %d
AND DATEDIFF(CURDATE(), date_waiting_pickup) % 7 = %d",
array(66, 0)
)
);
Any idea why? It runs fine in Terminal / direct MySQL. Is it the DIFFDATE() function?
EDIT: And interestingly enough, if I remove the $wpdb->prepare function, and leave $wpdb->get_results(), it works fine. So is there something I'm missing as far as how $wpdb->prepare() works?
In case that you want, as it seems, orders in the last week... Why don't you simplify it? There is no need for the second %d just put 0.
$followups =
$wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM orders
WHERE status_id = %d
AND DATEDIFF(CURDATE(), date_waiting_pickup) % 7 = 0",
66
)
);
UPDATE:
#dtj You are using mod (%) operator that give us the remainder of the division. So comparing with 0 (my first assumption) we obtain orders from today, 1 week ago, 2 week ago, etc.. If we compare with 1 (in the second %d) we obtain orders form yesterday, 8 days ago, etc...
Is really that what you want?
UPDATE 2: In your edited question you say that removing $wpdb->prepare() all works fine. No doubt is interesting, but fortunately you really don't need prepare() if you just works with integer numbers. I mean doing:
$status_id = (int) (is_numeric($status_id) ? $status_id : 0);
$followups = $wpdb->get_results("
SELECT * FROM orders
WHERE status_id = $status_id
AND DATEDIFF(CURDATE(), date_waiting_pickup) % 7 = 0");
you assure a safe query and gain in simplicity and efficiency. In my case I only use prepare() if there are strings involved and always test integer numbers as showed.
Im writing a pruning script, to delete content from my site that was uploaded over a week ago, and been accessed 0 or 1 times, also in the last week.
there are 2 tables:
daily_hits - which stores the item id, date, and number of hits that item got on that date.
videos - stores actual content
I came up with this.
$last_week_date = date('Y-m-d',$now-(60*60*24*7));
$last_week_timestamp = $now-(60*60*24*7);
SQL
SELECT
vid_id,
COALESCE(sum(hit_hits),0) as total_hits
FROM videos
LEFT JOIN daily_hits
ON vid_id = hit_itemid
WHERE (hit_date >= '$last_week_date') AND vid_posttime <= '$last_week_timestamp'
GROUP BY hit_itemid
HAVING total_hits < 2
This does output the items that were access once in the last week.... but not the ones that haven't been accessed at all. If an item wasn't accessed at all in that last week, there wont be any entries in the daily_hits table. I figured COALESE should take care of that, but that didnt work.
How can I fix this?
total_hits < 2
This guarantees "null hits" won't show up.
Make a second query that finds the nulls (it will show records from videos that have no corresponding key in daily_hits).
Make a UNION query to present the two datasets as one.
HAVING total_hits < 2 or total_hits is null