Nested Sum( ) query is not working in mysql - nested

i'm having a problem in calculating total bill of a ptient. I have three tables named as "test", "pharmacy", "check".
Columns in test are:
patient_ID
testname
rate
Columns in pharmacy are:
patient_ID
medicineDescription
qty
rate
Columns in check are:
patient_ID
doctorID
fees
date
I have a table Bill that will store total amount of a patient.
patient_ID
amount
date
I have used the following query. But it's giving the following error.
$result = mysqli_query($data, "SELECT patient_ID, (SUM(pharmacy.qty*pharmacy.rate ) + SUM(test.rate) + SUM(check.fees))
AS total FROM pharmacy, test, check WHERE patient_ID= '$pID'" );

Correct query should be, closing bracket was missing at the end of subquery (... AS total FROM pharmacy**)**):
$result = mysqli_query ($data, "SELECT patient_ID,
(SUM(pharmacy.qty*pharmacy.rate ) + SUM(test.rate) + SUM(check.fees)) AS total FROM pharmacy),
test,
check
WHERE patient_ID= '$pID'" );

You have three tables in your from clause, but with no join condition - this means you're pairing each row with all the other rows, which is obviously not what you intended. One way to handle this is to use proper joins:
SELECT p.patient_id, pharmacy_sum + test_sum + fees_sum AS total
FROM (SELECT patient_id, SUM(qty * rate) AS pharmacy_sum
FROM pharmacy
WHERE patient_ID= '$pID'
GROUP BY patient_id) p
JOIN (SELECT patient_id, SUM(rate) AS test_sum
FROM test
WHERE patient_ID= '$pID'
GROUP BY patient_id) t ON p.patient_id_id = t.patient_id
JOIN (SELECT patient_id, SUM(fees) AS fees_sum
FROM check
WHERE patient_ID= '$pID'
GROUP BY patient_id) c ON p.patient_id_id = c.patient_id

Related

Cassandra(Amazon keyspace) Query Error on clustered columns

I am trying execute query on clustering columns on amazon keyspace, since I don't want to use ALLOW FILTERING with my native query I have created 4-5 clustering columns for better performance.
But while trying to filter it based on >= and <= with on 2 clustering columns, I am getting error with below message
message="Clustering column "start_date" cannot be restricted (preceding column "segment_id" is restricted by a non-EQ relation)"
I had also tried with multiple columns query but I am getting not supported error
message="MultiColumn relation is not yet supported."
Query for the reference
select * from table_name where shard_id = 568 and division = '10' and customer_id = 568113 and (segment_id, start_date,end_date)>= (-1, '2022-05-16','2017-03-28') and flag = 1;
or
select * from table_name where shard_id = 568 and division = '10' and customer_id = 568113 and segment_id > -1 and start_date >='2022-05-16';
I am assuming that the your table has the following primary key:
CREATE TABLE table_name (
...
PRIMARY KEY(shard_id, division, customer_id, segment_id, start_date, end_date)
)
In any case, your CQL query is invalid because you can only apply an inequality operator on the last clustering column in your query. For example, these are valid queries based on your table schema:
SELECT * FROM table_name
WHERE shard_id = ? AND division = ?
AND customer_id <= ?
SELECT SELECT * FROM table_name \
WHERE shard_id = ? AND division = ? \
AND customer_id = ? AND segment_id > ?
SELECT SELECT * FROM table_name \
WHERE shard_id = ? AND division = ? \
AND customer_id = ? AND segment_id = ? AND start_date >= ?
All preceding columns must be filtered by an equality operator except for the very last clustering column in your query.
If you require a complex predicate for your queries, you will need to index your Cassandra data with tools such as Elasticsearch or Apache Solr. They will allow you to run complex search parameters to retrieve data from your database. Cheers!
ALLOW Filtering gets a bad rap sometimes. It all depends on how many rows you end up scanning. It's good to understand how many rows per partition will be scanned and work backwards from there. Only the last column can contain inequality statements to bound ranges. Try to order your columns to eliminate the most columns first, which reduce the number of rows 'Filtered'.
In the example below we used the index for keys up to start date and filtered on end_data, segment_id, and flag.
select * from table_name where shard_id = 568 and division = '10' and customer_id = 568113 and start_date >= '2022-05-16' and end_date > '2017-03-28') and (segment_id > -1 flag = 1;```

SQL query - SUM duration values (hh:mm:ss) from ALN field

I have table T1 with IDs:
ID
1
2
I have table T2 with ID and GROUP_TRACKING time because record can be multiple times at specific group. GROUP_TRACKING time is ALN type (STRING) and this cannot be changed but it contains always duration value in hh:mm:ss where hh column always has at least 2 characters but of course it can contain and more characters in case when record has been is some group for very long period of time:
ID GROUP GROUP_TRACKING
1 GROUP1 05:55:05
1 GROUP1 10:10:00
1 GROUP2 111:51:00
1 GROUP2 01:01:00
So I need to made SELECT clause from T1 table and to join T2 table to track for each group (G1 and G2) how much time it spent for that specific group.
So the final result should be like this:
ID GROUP1 GROUP2
1 16:05:05 112:52:00
2 null null
How to make this SELECT SUM of these duration in hours and minutes calculation?
Thank you
Here is a solution without the pivot step (which can be looked up in many other ansers)
with temp as (
select id
, group
, group_tracking
, SUBSTR(group_tracking, 1,LOCATE(':',group_tracking)-1) * 3600 as First_PART_in_s
, SUBSTR(group_tracking, LOCATE(':',group_tracking)+1,2) * 60 as Second_PART_in_s
, SUBSTR(group_tracking, LOCATE(':',group_tracking, LOCATE(':',group_tracking)+1)+1, 2) as Third_PART_in_s
from t2
)
select t1.id
, t.group
, int(sum(First_PART_in_s + Second_PART_in_s + Third_PART_in_s) / 360000) || replace(char(time('00:00:00') + mod(sum(First_PART_in_s + Second_PART_in_s + Third_PART_in_s),360000) seconds,ISO),'.',':') as duration
from t1
left join temp t
on t1.id = t.id
group by t1.id, group
I completly agree with #Clockwork-Muse that formats matter and using this inadequate format imposes lots of additional effort for reformatting or deconstructing and re-constructing things.

Select one column (with multiple rows) 5 times from the same table with different dates in the where clause

The DB records all user activity daily. I am trying to compile a summary report to display total number of actions per day per user. The problem is I want to stack the results next to each other. I have refered to the following stackoverflow questions.
mysql Select one column twice from the same table with different dates in the where clause
Select two columns from same table with different WHERE conditions
but I still continue to get the "subquery returns more than one row error #1242". All help is appreciated. Thank you.
This is my query, just for 2 days to start with.
SELECT LOGGEDIN_USER AS EnquiryHero,
( SELECT COUNT(user_id) from applications
DATE_TIME like "2016-08-24%" group by user_id ) as Day1,
( SELECT COUNT(user_id)from applications
WHERE DATE_TIME like "2016-08-25%" group by user_id ) as Day2,
from applications WHERE DATE_TIME like "2016-08-24%" group by user_id;
--
SELECT user_id,
( SUM( IF( the_day ='2016-08-24', ct, 0 ))) AS 2016-08-24,
( SUM( IF( the_day ='2016-08-25', ct, 0 ))) AS 2016-08-25,
( SUM( IF( the_day ='2016-08-26', ct, 0 ))) AS 2016-08-26,
( SUM( IF( the_day ='2016-08-27', ct, 0 ))) AS 2016-08-27,
FROM ( select user_id, DATE(date_time) AS the_day, loggedin_user, COUNT(*) AS ct
FROM applications GROUP BY 1,2 ) AS x
GROUP BY user_id;
First focus on getting the data; then focus on "pivoting" the data.
SELECT user_id,
DATE(`date_time`) AS the_day,
COUNT(*) AS ct
FROM applications
GROUP BY 1, 2;
See if that gives you the data desired; then look at how to "pivot". See the extra tag I added.
Then pivot
SELECT user_id,
(SUM(IF(the_day = '2016-08-24', ct, 0) AS '2016-08-24',
(SUM(IF(the_day = '2016-08-25', ct, 0) AS '2016-08-25',
(SUM(IF(the_day = '2016-08-26', ct, 0) AS '2016-08-26',
(SUM(IF(the_day = '2016-08-27', ct, 0) AS '2016-08-27',
...
FROM (
the query above
) AS x
GROUP BY user_id;

Can I reuse the result of a subquery to optimize the overall query?

I am using below query to fetch the top two records for profile_run_key. I am using three almost similar queries to get this done. This means I am traversing the table thrice for the "where" clause. So I think this will take 3(n) time for execution. Alternatively I can use "Order by" but the it will take nlogn time to execute.
SELECT name, weighted_average
FROM idp_weighted_avg
where (profile_run_key =
(SELECT MAX (profile_run_key)
FROM idp_weighted_avg
WHERE SCORECARD_IDENTIFIER = 'U:D8yIYvW6EeGKyklcM7Co1A')
OR profile_run_key =
(SELECT MAX (profile_run_key)
FROM idp_weighted_avg
WHERE SCORECARD_IDENTIFIER = 'U:D8yIYvW6EeGKyklcM7Co1A'
AND profile_run_key <
(SELECT MAX (profile_run_key)
FROM idp_weighted_avg
WHERE SCORECARD_IDENTIFIER =
'U:D8yIYvW6EeGKyklcM7Co1A')))
I was wondering if I can reuse (I don't want to create a temp table) the result of the below sub query? Any alternatives? Sugestions?
SELECT MAX (profile_run_key)
FROM idp_weighted_avg
WHERE SCORECARD_IDENTIFIER = 'U:D8yIYvW6EeGKyklcM7Co1A'
It seems like you are selecting the two largest records for a given SCORECARD_IDENTIFIER. If that's what you realy are after, you can add
a ROW_NUMBER
PARTITION BY SCORECARD_IDENTIFIER - Restarts the rownumber for each group
ORDER BY profile_run_key DESC - Numbers the key in a group from hig to low
SQL Statement
SELECT *
FROM idp_weighted_avg wa
INNER JOIN (
SELECT profile_run_key
, rn = ROW_NUMBER() OVER (PARTITION BY SCORECARD_IDENTIFIER ORDER BY profile_run_key DESC)
FROM idp_weighted_avg
WHERE SCORECARD_IDENTIFIER = 'U:D8yIYvW6EeGKyklcM7Co1A'
) rn ON rn.profile_run_key = wa.profile_run_key
WHERE rn <= 2

SQL query for SQL Server Compact Edition 3.5 - GROUP BY issue

SELECT BabyInformation.* , t1.*
FROM BabyInformation
LEFT JOIN
(SELECT * FROM BabyData
GROUP BY BabyID
ORDER By Date DESC ) AS t1 ON BabyInformation.BabyID=t1.BabyID
This is my query. I want to get the one most recent BabyData tuple based on date.
The BabyInformation should left join with babyData but one row per baby...
I tried TOP(1) but this worked only for the first baby
Here is one way to do it, there are other ways which can be faster, but I believe this one to be the clearest for a beginner.
SELECT BabyInformation.*, BabyData.*
FROM BabyInformation
JOIN
(SELECT BabyID, Max(Date) as maxDate FROM BabyData
GROUP BY BabyID
) AS t1
ON BabyInformation.BabyID=t1.BabyID
Join BabyData ON BabyData.BabyID = t1.BabyID and BabyData.Date = t1.maxDate
This should do it:
SELECT bi.* , bd.*
FROM BabyInformation [bi]
LEFT JOIN BabyData [bd]
on bd.BabyDataId = (select top 1 sub.BabyDataId from BabyData [sub] where sub.BabyId = bi.BabyId order by sub.Date desc)
I've assumed that there is a column called 'BabyDataId' in the BabyData table.

Resources