mysql count brings back at least 1 row - mysql

I've recently moved jobs and gone from a working with T-SQL to MySql. So far so good until today.
i'm running the following sql script:
SELECT PB.idproductbundle AS ID,
PB.Name AS Name,
PB.Discount AS Discount,
PB.DiscountIsPercent AS DiscountIsPercent,
COUNT(PB_P.idproductbundle) AS ProductCount
FROM `mydb`.productbundles AS PB
LEFT JOIN `mydb`.ProductBundle_Product PB_P ON PB_P.idproductbundle = PB.idproductbundle
simple command to bring back all product bundles with a count of how many products in that bundle.
Strange thing is, there is currently no data in tables: productbundles or ProductBundle_Product.
but it insits on bringing back 1 row. all the columns are their default value:
ID Name Discount DiscountIsPercent ProductCount
NULL, NULL, NULL, NULL, '0'
In T-Sql this would have no rows.

Because you have a COUNT clause in the select, which will bring back a zero if there are no rows that satisfy the query. So you're guaranteed at least one row - the result of the COUNT telling you there are zero rows.

Turns out i was missing a group by :/
SELECT PB.idproductbundle AS ID,
PB.Name AS Name,
PB.Discount AS Discount,
PB.DiscountIsPercent AS DiscountIsPercent,
COUNT(PB_P.idproductbundle) AS ProductCount
FROM `ukiss-order-management`.productbundles AS PB
LEFT JOIN `ukiss-order-management`.ProductBundle_Product PB_P ON PB_P.idproductbundle = PB.idproductbundle
GROUP BY PB.idproductbundle

Related

Unknown Column in Where Clause When Using the Variable Created with AS

The question is about using a column (which is created in query) as where clause criteria.
There are 2 tables named transactions and transactionmovements.
In transaction, there are unique info for transaction like date, counterparty etc.
In transactionmovements, there are articles which is used in transaction. Such as product, quantity, price, etc. And transactionmovements has a 'transaction' column which references to transactions.id shows which transaction the movement belongs.
In the query, I created a totalPrice value with sum of quantity*price of each movement that belongs to a transaction.
Everything works perfectly but the last parameter of WHERE clause. If I delete "AND
totalPrice > 10" part, it gives me everything including totalPrice and totalQuantity of a transaction.
But if I place "AND totalPrice > 10" to the end, it returns following error:
-#1054 - Unknown column 'totalPrice' in 'where clause'
SELECT
`transactions`.id,
`transactions`.type,
`transactions`.date,
`transactions`.VAT,
`transactions`.currency,
`companies`.name AS counterparty,
COALESCE
(sum(`transactionmovements`.price*`transactionmovements`.quantity)
+(`transactions`.shippingQuantity*`transactions`.shippingPrice)) as totalPrice,
COALESCE
(sum(`transactionmovements`.quantity)) as totalQuantity
FROM
`transactions`
LEFT JOIN `companies` ON `transactions`.counterparty = `companies`.id
LEFT JOIN `transactionmovements` ON `transactions`.id=`transactionmovements`.transaction
WHERE ( `transactions`.type = 'p' OR `transactions`.type = 'r' OR `transactions`.type = 's' OR `transactions`.type = 't')
AND
(`transactions`.date BETWEEN IFNULL('','1900-01-01') AND IFNULL('2020-02-14',NOW()))
AND
totalPrice > 10
GROUP BY `transactions`.id
ORDER BY id desc
LIMIT 10
I tried using the whole math operation in WHERE clause, but no gains. I tried to use HAVING with WHERE but couldn't manage it.
The last solution I have is running it without filtering by totalPrice and store it into a php array. Then filter in array, but there I can't use LIMIT so array will be very big.
As per how SQL query are executed in the order that dictate SELECT is executed after WHERE, you can't use ALIAS in WHERE since it is unknown at the moment. Therefor, you should change every alias uses outside of SELECT to its definition.
As Thomas Jeriko suggested in comments, creating a view was exactly what I need.
First I create a virtual table with Create View.
CREATE VIEW transactionreportview
AS SELECT
transactions.id id,
transactions.type type,
transactions.date date,
transactions.VAT VAT,
transactions.currency currency,
transactions.counterparty counterparty,
(SUM(transactionmovements.price*transactionmovements.quantity)+transactions.shippingQuantity*transactions.shippingPrice) totalPrice,
SUM(transactionmovements.quantity) totalQuantity
FROM transactions transactions, transactionmovements transactionmovements
WHERE transactions.id = transactionmovements.transaction
GROUP BY transactions.id;
While the virtual table acts like a simple mysql table, I ran a new query in the table
SELECT * FROM transactionReportView WHERE ..."
Then after finishing my work with the virtual table, drop it
DROP VIEW transactionreportview

Use subquery in mysql

The query below gives me 2 out of the 3 answers I'm looking for. On the sub-query select I get null instead of no
the 3 possible values for column name isCyl could be blank, yes, no
I'm not sure if the sub-query is the best way to go about it, but I don't know how else to re-state the query.
The schedule table has a series of columns to show what tasks must be completed on an assignment. Related tables store the results of the tasks if they were assigned to be completed. So I need to test if a specific task was scheduled. If so, then I need to see if the results of the task have been recorded in the related table. For brevity I am only showing one of the columns here.
SELECT s.`reckey`,
if(s.cylinders="T",
(select
if(c.areckey is not null,
"yes",
"no"
)
from cylinders c where c.areckey = s.reckey limit 1
)
,""
) as isCyl
from schedule s
where s.assignmentDate between 20161015 and 20161016
order by s.reckey
Use a LEFT JOIN, which returns NULL for columns in the child table when there's no match.
SELECT s.reckey, IF(s.cylinders = "T",
IF(c.areckey IS NOT NULL, 'yes', 'no'),
"") AS isCyl
FROM schedule AS s
LEFT JOIN cylinders AS c ON c.areckey = s.reckey
WHERE s.assignmentDate between 20161015 and 20161016
ORDER BY s.reckey
If there can be multiple rows in cylinders with the same areckey, change it to:
LEFT JOIN (select distinct areckey FROM cylinders) AS c on c.areckey = s.reckey
or use SELECT DISTINCT in the main query.

how to joining two group-by queries

alright this is my mistakes, I asked question that nobody would understand it, now I'm trying to make my question clearer and more simple.
Here I've 3 tables, first is employeeid contains (nameid, salary), second is overtimeid contains (nameid 'from employeeid', period, tot_ot), and the third is absenceid contains (nameid 'from employeeid', period, tot_absence).
how can I populate those three tables into one query containing (nameid, salary, period (fr overtimeid should be the same with absenceid), tot_ot, tot_absence).
please help me master of ms-access, I can't do wonder thing without your help,..... thanks before.
You can use query like this:
SELECT nameid, period, Sum(tot_absence) AS SumOftot_absence, Sum(tot_ot) AS SumOftot_ot
FROM
(SELECT nameid, period, tot_absence, Null AS tot_ot
FROM absenceid
UNION ALL
SELECT nameid, period, Null AS tot_absence, tot_ot
FROM overtimeid)
GROUP BY nameid, period;
Then outer join it with employeeid and you will receive the list of employees for each period
Edit
Query for tables from comments:
SELECT NMKARY, PERIODGJ, sum(JMLMBUR) as sumofJMLMBUR, sum(TOTABS) as sumofTOTABS, sum(KASBON) as sumofKASBON
FROM (
SELECT NMKARY, PERIODGJ, JMLMBUR, Null as TOTABS, Null as KASBON
FROM overtimeid
Union ALL
SELECT NMKARY, PERIODGJ, Null as JMLMBUR, TOTABS, KASBON
FROM potonganid
)
GROUP BY NMKARY, PERIODGJ;

MYSQL: show registers, relate and rename

The instructions are the following:
Generate a report of all the products purchased by the customers where it appears: the id of the customer, the customer's full name, the city, the state, the ID number, the date of sale, the product code, the product name, the quantity sold and finally a message that says "you paid" or "payment Pending" status depending on the payment status where 0 = paid and 1 = pending. This report should appear sorted alphabetically first by state and then by customer name.
what I tried is this:
select cli_nom, cli_city, cli_state, fac_num, fac_saledate, prod_cod, fac_total, fac_status
where fac_status = 0 as paid and fac_status = 1 as pending
from factures, products, clients order by cli_state, cli_nom, asc;
Wich absolutley didnt work, Im not sure about the sintax to rename or mask a column.
The table structures are the following:
table clientes:
1. cli_nom varchar(100)
2. cli_state varchar(100)
3. cli_city varchar(100)
4. cli_id int(11)
5. cli_status int(11)
6. cli_dateofsale date
table products:
1. prod_cod int(11)
2. prod_categ char(1)
3. prod_nom varchar(100)
4. prod_price double
5. prod_descrip varchar(100)
6. prod_discount float
table facturas:
1. fac_num int(11)
2. fac_datesold date
3. fac_cli_id int(11)
4. fac_status int
5. fac_total float
You are having a trouble with the querys.
When you want to query something, the form of the complete statement is something like this
Select [fields]
from [table(s)] --which means there includes inner joins
where [filter rows]
group by [fields to group]
having [filtering groups]
order by [fields]
Of course, is something much more complicated and bigger than this, but it will give you some initial concepts.
You will always have to respect this order, so in your query are putting a where into the select.
If you want to change something to show, dependending on some evaluation, but you will ALWAYS show something (you are not filtering, you are choosing what to show according to the value), you can use CASE clause.
In this example, you could do something like this
select cli_nom, cli_city, cli_state, fac_num, fac_saledate,
prod_cod, fac_total, fac_status
CASE when fac_status = 0 then 'You Paid'
when fac_status = 1 then 'payment Pending'
else 'Not sure about state' END
from factures
inner join products on --put here how do you relate products with factures
inner join clients on -- put here how do you relate clients with products/factures
order by cli_state, cli_nom, asc;
If you don't know how to use INNER JOIN, here you have some info.
Basically, is a clause that is used to relate two tables.
something like
(..)
from Table1 A
INNER JOIN Table2 B on A.id = B.id
(A and B are aliases, and representing the table that have set).
This means that it will compare every row from Table1 to every row from Table2, and when the condition is matched (in this case id from table1 [A.id] equals id from Table2 [= B.id]) then that relation-row is showed (means that it will show you all the row from table1 + all the row from table2)

MySQL query was working before, now it isn't?

I'm having an odd problem, and I don't have the slightest idea of why it isn't working.
I have the following query that I constructed:
SELECT servers.id, servers.name, servers.address, servers.port, servers.up, servers.down, servers.genre, servers.score, servers.version, servers.country, ROUND( AVG( reviews.average ) , 0 ) AS review
FROM servers
INNER JOIN reviews ON servers.id = reviews.server
ORDER BY servers.score DESC
This query was working fine a few weeks ago. It is meant to get many fields from the "servers" table, and the average field from the "reviews" table where the server in the "reviews" table is the same as the id in the "servers" table.
Like I said, this query was working fine before. Yesterday I noticed that a vital part of my site wasn't working, and I figured out that this query is failing.
I've confirmed that is returning exactly 1 row (when, at the moment, it should be returning 4, because there are 4 entries in the "servers" table.)
This is what phpMyAdmin gives me when I execute that query:
id name address port up down genre score version country review
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
Could anybody enlighten me? I've come here as a last resort, because I am stuck.
As mentioned in the comments, try changing the INNER JOIN to a LEFT OUTER JOIN which will return servers, regardless if there is a matched row in the review table or not. Also, you didn't post your schema, but double check the reviews.server column in the reviews table, it may be server_id instead. Another issue, you are doing an AVG which is a grouped calculation, but you have no GROUP BY clause, so I would suggest adding it, so your full query should look like:
SELECT servers.id, servers.name, servers.address, servers.port, servers.up, servers.down, servers.genre, servers.score, servers.version, servers.country, ROUND( AVG( reviews.average ) , 0 ) AS review
FROM servers
LEFT OUTER JOIN reviews ON servers.id = reviews.server # might be reviews.server_id
GROUP BY reviews.server
ORDER BY servers.score DESC
More info about GROUP BY functions.
-- Update --
SELECT servers.id, servers.name, servers.address, servers.port, servers.up, servers.down, servers.genre, servers.score, servers.version, servers.country, IFNULL(ROUND(AVG(reviews.average)), 0) AS review
FROM servers
LEFT OUTER JOIN reviews ON servers.id = reviews.server
GROUP BY servers.id
ORDER BY servers.score DESC