GROUP_CONCAT within CONCAT - mysql

Database hierarchical structure is as follow
Student Name List of fee Assigned to Each
Student
List of Scholarship Assigned to Each Fee
As structure, expected output is
Student Name-Fee->Scholarship1, Scholarship2
Karan-1.Annual Fee->Economic Scholarship,Incapable Scholarship,2.Monthly Fee
But what I am getting
Student Name-Fee->Scholarship1, Student Name-Fee->Scholarship2
Karan-1.Annual Fee->Economic Scholarship,1.Annual Fee->Incapable Scholarship,2.Monthly Fee
What is wrong in here ? Though I am nesting CONCAT, but not getting expected output
CONCAT(student.en_ttl,'-',GROUP_CONCAT(DISTINCT fee.id,'.',fee.en_ttl,
COALESCE(CONCAT('->',sch.en_ttl),''))) AS fee
SQL Fiddle

You basically need to two levels of GROUP BY. So, we will need to use a Derived Table here. First subquery will aggregate at the level of fee; and then the second level would aggregate those fee details at the level of student.
Also, in newer (and ANSI SQL compliant) versions of MySQL, you need to ensure that any non-aggregated column in the SELECT clause should be in the GROUP BY clause as well.
Query
SELECT
CONCAT(stud_ttl,'-',GROUP_CONCAT(CONCAT(fee_det, COALESCE(CONCAT('->',fee_sch), '')))) AS fee
FROM
(
SELECT student.ttl AS stud_ttl,
CONCAT(fee.id,'.',fee.ttl) AS fee_det,
Group_concat(DISTINCT sch.ttl) AS fee_sch
FROM inv_id
JOIN student
ON student.id = inv_id.std
JOIN inv_lst
ON inv_lst.ftm = inv_id.ftm
JOIN fee
ON fee.id = inv_lst.fee
JOIN sec_fee
ON sec_fee.fee = fee.id
AND sec_fee.cls = student.cls
AND sec_fee.sec = student.sec
LEFT JOIN std_sch
ON std_sch.std = student.id
LEFT JOIN sec_sch
ON sec_sch.sch = std_sch.sch
AND sec_sch.fee = fee.id
LEFT JOIN sch
ON sch.id = sec_sch.sch
GROUP BY student.ttl, fee_det, fee.ttl
) dt
GROUP BY stud_ttl;
Result
| fee |
| -------------------------------------------------------------------- |
| Karan-1.Annual->Economic Scholarship,Incapable Scholarship,2.Monthly |
View on DB Fiddle

Related

SQL Distinct based on different colum

I have problem to distinct values on column based on other column. The case study is:
Table: List
well | wbore | op|
------------------
wella|wbore_a|op_a|
wella|wbore_a|op_b|
wella|wbore_a|op_b|
wella|wbore_b|op_c|
wella|wbore_b|op_c|
wellb|wbore_g|op_t|
wellb|wbore_g|op_t|
wellb|wbore_h|op_k|
So, I want the output to be appear in different field/column like:
well | total_wbore | total_op
----------------------------
wella | 2 | 3
---------------------------
wellb | 2 | 2
the real study case come from different table but to simplify it I just assume this case happened in 1 table.
The sql query that I tried:
SELECT well.well_name, wellbore.wellbore_name, operation.operation_name, COUNT(*)
FROM well
INNER JOIN wellbore ON wellbore.well_uid = well.well_uid
INNER JOIN operation ON wellbore.well_uid = operation.well_uid
GROUP BY well.well_name,wellbore.wellbore_name
HAVING COUNT(*) > 1
But this query is to calculate the duplicate row which not meet the requirement. Anyone can help?
you need to use count distinct
SELECT
count(distinct wellbore.wellbore_name) as total_wbore
count(distinct operation.operation_name) as total_op
FROM well
INNER JOIN wellbore ON wellbore.well_uid = well.well_uid
INNER JOIN operation ON wellbore.well_uid = operation.well_uid
Final query:
SELECT
well.well_name,
COUNT(DISTINCT wellbore.wellbore_name) AS total_wbore,
COUNT(DISTINCT operation.operation_name) AS total_op
FROM well
INNER JOIN wellbore ON wellbore.well_uid = well.well_uid
INNER JOIN operation ON wellbore.well_uid = operation.well_uid
GROUP BY well.well_name

Understanding MySQL return

The MySQL query is:
SELECT orders.scientific_name AS 'Order',
families.scientific_name AS 'Family',
COUNT(*) AS 'Number of Birds'
FROM birds, bird_families AS families, bird_orders AS orders
WHERE birds.family_id = families.family_id
AND families.order_id = orders.order_id
AND orders.scientific_name = 'Pelecaniformes';
The Output is:
+----------------+-------------+-----------------+
| Order | Family | Number of Birds |
+----------------+-------------+-----------------+
| Pelecaniformes | Pelecanidae | 224 |
+----------------+-------------+-----------------++
But I have 5 Families in the DB. Why did it return only one?
You are using COUNT(*) which turns this into an aggregation query. Without a GROUP BY, this returns exactly one row.
I would recommend getting started by:
Removing the COUNT(*).
Replacing the commas with explicit JOIN syntax.
Use table aliases.
Don't use single quotes for column aliases.
Then work toward the query you really want to write. So, to get started:
SELECT o.scientific_name AS `Order`,
bf.scientific_name AS Family
FROM birds b JOIN
bird_families bf
ON b.family_id = bf.family_id JOIN
bird_orders bo
ON bf.order_id = o.order_id
WHERE o.scientific_name = 'Pelecaniformes';
At this point, you can probably add the COUNT(*) and GROUP BY o.scientific_name, bf.scientific_name.
If you have 5 Families in the orders.scientific_name = 'Pelecaniformes'
then you should use group by
SELECT orders.scientific_name AS 'Order',
families.scientific_name AS 'Family',
COUNT(*) AS 'Number of Birds'
FROM birds, bird_families AS families, bird_orders AS orders
WHERE birds.family_id = families.family_id
AND families.order_id = orders.order_id
AND orders.scientific_name = 'Pelecaniformes'
Group by orders.scientific_name , families.scientific;

MYSQL - JOIN table filter not working

I have four table each table connected with some id kindly see the below query how I'm getting
SELECT
tax_rates.name,
IF( products.tax_method = 0, 'Inclusive', 'Exclusive') AS type,
IF((SUM(purchases.grand_total) > 0),(SUM(purchases.grand_total)),(SUM(purchase_items .subtotal))) AS total_amount,
IF((SUM(purchases.order_tax) > 0),(SUM(purchases.order_tax)),SUM(purchase_items .item_tax)) AS tax_amount
FROM tax_rates
LEFT JOIN purchases ON purchases.order_tax_id = tax_rates.id
LEFT JOIN purchase_items ON purchase_items.tax_rate_id = tax_rates .id
LEFT JOIN products ON products.id = purchase_items.product_id
WHERE purchases.warehouse_id = 1
GROUP BY tax_rates.id, products.tax_method
ORDER BY tax_rates.name desc LIMIT 0, 10
The above query didn't return any result but if I remove WHERE purchases.warehouse_id = 1 then it display the result. I don't know where I'm doing the mistake. Kindly correct me.
Sorry to tell about this I'm try to get purchase order tax and purchase Item tax
in particular store and date
Output
name type total_amount tax_amount
VAT #20% Inclusive 11005.2000 1834.2000
VAT #10% Inclusive 165.0000 15.0000
No Tax Exclusive 204771.4000 0.0000
GST #6% Exclusive 7155.0000 405.0000
GST #6% Inclusive 7155.0000 405.0000
Thank you
Data type? purchases.warehouse_id = '1'?
You should not add the condition in where clause, when you are using the field of the left join table. so remove the where clause and use like below
LEFT JOIN purchases ON purchases.order_tax_id = tax_rates.id and purchases.warehouse_id = 1
If you try to add the left join table field in where clause it will become INNER JOIN. hence it may not display any rows according to your data.

Complex SQL query. At least for me

I am trying to pull invoice data from my database based on a PatientID. I am trying to figure out which invoices belong to which patient. Here is the important parts of my structure.
Invoices Table
InvoiceNumber | DateInvoice | DueDate | StudyID | TypeInvoice
Patients Table
FirstName | LastName | PatientID
InvoiceFields
id | InvoiceNumber | PatientID |
I need make a query that lists the invoice table data based upon a PatientID. Below is the query that I attempted, but got no where with. Thank you for your time.
SELECT Distinct
invoicefields.InvoiceNumber,
invoices.DateInvoice
FROM `invoices`, `patients`, `invoicefields`
WHERE invoicefields.PatientID = patients.PatientID
and invoicefields.InvoiceNumber = invoicefields.InvoiceNumber
GROUP BY invoicefields.InvoiceNumber
SELECT InvT.InvoiceNumber, InvT.DateInvoice
FROM InvoiceTable InvT
INNER JOIN InvoiceFields InvF ON InvF.InvoiceNumber = InvT.InvoiceNumber AND InvF.PatientID = #PatientID
So pretty much since you only need data from the InvoiceTable and you indicate you have the PatientID. I propose you just join to the Cross Reference table InvoiceFields and use the PatientID column in that query to filter it down to what you need. I had a more complex example using an exist before I realized you didn't need anything from Patients.
You could use this if you need information on the Patient as well (Just put the needed columns in the Select)
SELECT InvT.InvoiceNumber, InvT.DateInvoice
FROM InvoiceTable InvT
INNER JOIN InvoiceFields InvF ON InvF.InvoiceNumber = InvT.InvoiceNumber AND InvF.PatientID = #PatientID
INNER JOIN Patient Pat ON Pat.PatientID = InvF.PatientID
You can put the #PatientID portion on the join for either Patient or InvoiceFields. There really shouldn't be a performance difference between either way if you indexes are right.
The Response to the Below Comment but where I can show it cleaner:
SELECT IT.InvoiceNumber
,IT.DateInvoice
FROM InvoiceTable InvT
WHERE EXISTS (SELECT InvF.PatientID
FROM InvoiceFields InvF
WHERE InvF.InvoiceNumber = InvT.InvoiceNumber
AND InvF.PatientID = #PatientID)
This will return all the rows for the patient from InvoiceTable and if InvoiceNumber is Unique will not have any duplicates. Though this way you only have access to InvoiceTable to return Data from. If you only want one put a TOP 1 on it:
SELECT TOP 1 IT.InvoiceNumber
,IT.DateInvoice
FROM InvoiceTable InvT
WHERE EXISTS (SELECT InvF.PatientID
FROM InvoiceFields InvF
WHERE InvF.InvoiceNumber = InvT.InvoiceNumber
AND InvF.PatientID = #PatientID)
SELECT * from invoices i
inner join invoicefields iFld
on i.invoiceNumber = iFld.invoiceNumber
inner join patients p
on iFld.patientID = p.patientID
and p.patientID = 1235125
This should get you started in the right direction at least. I'm not sure what columns you wanted to return and/or if there's any nulls in the tables. Nulls will affect which rows are returned

counting methodolegy in SQL Server query

Good day everyone…
I have a database that has the following:
Division table that linked to Employee table.
Group table, i.e. courses categories, that linked to Courses table.
and these table linked together thru Curses_Employee table .
so far I managed to come up with a query that give me the number of users who toke certain course in each group/category like the following output table:
groupName | DivisionName| courseName|Total Number of Participants
and here is my query for the above scheme:
SELECT dbo.groups.GroupName, dbo.Divisions.DivisionName, dbo.courses.CourseName, COUNT(dbo.employee_courses.courseId) AS [Total Number of Participants]
FROM dbo.employee AS employee_1 INNER JOIN
dbo.Divisions ON employee_1.DivisionCode = dbo.Divisions.SapCode INNER JOIN
dbo.employee_courses ON employee_1.Username = dbo.employee_courses.employeeId INNER JOIN
dbo.courses ON dbo.employee_courses.courseId = dbo.courses.CourseID INNER JOIN
dbo.groups ON dbo.courses.GroupID = dbo.groups.ID
WHERE (dbo.courses.GroupID = 2)
GROUP BY dbo.courses.CourseID, dbo.courses.CourseName, dbo.Divisions.DivisionName, dbo.groups.GroupName
now I want to add two columns the total number of employee in each division as well as the % like the following table:
groupName | DivisionName| courseName|Total Number of Participants |Total Number of Employee |%
I tried this query but it give me an error:
SELECT dbo.groups.GroupName, dbo.Divisions.DivisionName, dbo.courses.CourseName, COUNT(dbo.employee_courses.courseId) AS [Total Number of Participants],
(SELECT COUNT(Name) AS Expr1
FROM dbo.employee
WHERE (DivisionCode = employee_1.DivisionCode)
GROUP BY DivisionCode) AS [Total Number of Employee]
FROM dbo.employee AS employee_1 INNER JOIN
dbo.Divisions ON employee_1.DivisionCode = dbo.Divisions.SapCode INNER JOIN
dbo.employee_courses ON employee_1.Username = dbo.employee_courses.employeeId INNER JOIN
dbo.courses ON dbo.employee_courses.courseId = dbo.courses.CourseID INNER JOIN
dbo.groups ON dbo.courses.GroupID = dbo.groups.ID
WHERE (dbo.courses.GroupID = 2)
GROUP BY dbo.courses.CourseID, dbo.courses.CourseName, dbo.Divisions.DivisionName, dbo.groups.GroupName
the error message:
column 'dbo.employee.DivisionCode' is invalid in the select list
because it is not contained in either as aggregate function or the
GROUP BY clause.