Trying to get a count (to later multiply with a rate) of names in upto (if data is present in one or more) four rows. In other words, there is a price per person occupying a room. So, I want to count the number of persons in the room by names entered on the form and saved in the database table.
I could simply add a field where the user also selects the number of people in addition to completeing the name fields but this seems redundant (and prone to error).
Setup
Table: 1.clients which has columns:
id,
tourbk_id,
tourstart,
roomtype1,
client1_name,
client2_name,
client3_name,
client4_name
Question
I have a query which currently checks the roomtype to the per person price for that room type and is working to produce the result but, of course, it is only returning (for two people in a room) the price person for double occupancy.
E.g.: (per person prices)... single = $10; double = $20; triple = $30; quad = $40
My current result for double room is $20 (which echo's next to "Price per person". I need a query to count the total persons in this double and multiple times the rate ... "Total: query[$20 * 2]"
How do I code a query to count the "client_name" entries in a table?
Here I've added a virtual column named ClientCount which is the count of clients in the room. I like to use client1_name > '' because it works whether you use blanks or NULLs, and saves me from asking a question.
SELECT
id,
tourbk_id,
tourstart,
roomtype1,
client1_name,
client2_name,
client3_name,
client4_name,
CASE WHEN client1_name > '' THEN 1 ELSE 0 end +
CASE WHEN client2_name > '' THEN 1 ELSE 0 end +
CASE WHEN client3_name > '' THEN 1 ELSE 0 end +
CASE WHEN client4_name > '' THEN 1 ELSE 0 end ClientCount
FROM TBL
You ought to consider normalising your schema by having a separate client_names table that relates a single name column to a single booking identifier: multiple clients would then be represented by multiple records in that new table. You would count clients with:
SELECT COUNT(*) FROM client_names WHERE booking_id = ...
However, with your current structure (and assuming that the name columns are NULL if there is no such client), you could do:
SELECT (client1_name IS NOT NULL)
+ (client2_name IS NOT NULL)
+ (client3_name IS NOT NULL)
+ (client4_name IS NOT NULL)
AS client_count
FROM clients
-- etc.
and, as a round-about way of doing it I thought of the following which also works (will just need to make a case for the 1, 2, 3, and 4 ["if roomtype1='sgl', then $mult=1, if roomtype='dbl', then $mult=2...] multiplyer to check for the other room types):
$total = ($roomrate['roomprice'] * 2);
echo "Total this booking : ";
echo $total;
thanks to all for the help!
Related
In an interface where user records in a table can be searched.
The operator must be able to search by the age and/or the gender of the user(the record). However this must be done by using the ID number of the user captured.
This is possible, as the ID number can be broken down into usable data.
An ID number has 13 DIGITS:
eg. 6911205062080
Which can be broken down as follows:
YYMMDDSSSSCAZ
Where (YYMMDD) refers to date. 20 November 1969 is shown as 691120
(SSSS) refers to gender. Females are assigned numbers in the range 0000-4999 and males from 5000-9999
CAZ also carries meaning however they are not relevant to the context of the question. `
The user can choose to search All ages, or select from three age brackets:
A:18-38, B:39-59, C:60 upwards.
-They can select one option[ A or B or C]
-Or They can select two options[A and B,A and C or B and C],
-Or They can select all 3 options[A and B and C], meaning all of them)
This means that if they op not to search all of the age groups, an array containing their selection gets posted.
When selecting gender:
-They can search all genders[Male & Female]
-Or Choose one option [Either Male or Female]
The data gets sent to me and now I have to manipulate the data to return the correct records.
Now I know I have to use substrings. The ID field is stored as character varying however to establish the age I would have to substring the (YYMMDD) part and cast it to a date in order to correctly compare it, and the (SSSS) would have to be cast to an integer to establish if it is smaller than 5000
This is my code so far:
if($_POST['gender'] == 'all'){
$gender="";
}elseif($_POST['gender'] == 'male'){
$gender = " and userIDNumber = "."ESTABLISH ALL ID's THAT ARE MALE";
}elseif($_POST['gender'] == 'female'){
$gender = " and userIDNumber = "."ESTABLISH ALL ID's THAT ARE FEMALE";
}
$age = "";
if($_POST['radioAge'] == 'select'){
$branches = " and userIDNumber in (SELECT A WAY TO FIND OUT HOW TO ESTABLISH THE AGES THAT FALL IN THE GROUPS SPECIFIED BY THIS ARRAY in(". implode(",", $_POST['age_group']).")) ";
}
$query = "SELECT * FROM user_table WHERE status='Active'".$gender.$age;
Using PHP and SQL, how would I go about using the posted gender selections and age selections to find the correct ID numbers and as a result, the correct records?
for the gender try something like this:
if($_POST['gender'] == 'all'){
$gender="";
}elseif($_POST['gender'] == 'male'){
$gender = "and CONVERT(SUBSTR(userIDNumber, 6, 4), INTEGER) < 5000";
}elseif($_POST['gender'] == 'female'){
$gender = "and CONVERT(SUBSTR(userIDNumber, 6, 4), INTEGER) >= 5000";
}
First you need to extract the information from the ID-s for the year part:
You need to use substring and string contatenation for this.
After that you need convert it to date and use the now() function to get the date difference. SELECT DATEDIFF(year, '2011-10-02', '2012-01-01');
Finaly you need to create between branches like this:
... where DATEDIFF(year, '2011-10-02', now()) between 18 and 38 ...
Gender:
Same way, extract the information from id with substring, cast it to numeric.
... where CAST(substring(ID) as numeric) <5000 --female
You also need to create the AND , OR operators.
As the headline states, I'd like to know how to insert both a random number generated with php, and selected lines from another table. Example:
<?php
$randomid = (rand(1,1000000));
$sql = "INSERT INTO example2 (randomid, userid, name)
VALUES ('$randomid')
SELECT userid, name
FROM example1
WHERE name='Donald' "
$mysqli->query($sql);
?>
I'm not sure how to go about this. Must I divide this into an insert and an update query?
SELECT in MySQL can be used to output message/static values like in this example
SELECT CASE
WHEN userid<100 THEN 'less than 100'
WHEN userid<200 THEN 'less than 200'
ELSE 'greater than 200'
END AS message, userid
FROM mytable
so in your example you can just do the same
$randomid = (rand(1,1000000)); // <--- imagine 25 was returned
$sql = "INSERT INTO example2 (randomid, userid, name)
SELECT ".$randomid.", userid, name
FROM example1
WHERE name='Donald' " // <--- you select now looks like 'SELECT 25, userid, name'
however there is a downside as this will give every entry with the name Donald the same value so if you have multiple Donalds it kinda defeated the purpose of a random value unless you plan to limit the insert to do one at the time giving your PHP rand function to recalculate
a better way to do this is with MySQL's own RAND function
Returns a random floating-point value v in the range 0 <= v < 1.0.
ofcause since this function returns a decimal/float value which isn't really ideal for an integer key we want to make it into a inetger by mutiplying it and using FLOOR by using this
FLOOR(RAND()*1000000) AS randomid
Fiddle
this will get us a value between 0 and 1, we multiply it by 1000000 and then round it down to the nearest full number using FLOOR and unlike the PHP code a new number is created for every entry. so 15 Donalds will have 15 different random ids. there is still the possibility that you can get identical number but thus is the nature of random number
let me explain my purpose first, i have an vehicle booking application where, visitor will add start date and end date of his journey, in the database there is list of drivers with there availability (available_from_date and available_to_date) which is kind of duration during which they are operating, there is an field for exclude_dates for some specific dates when they are not working.
the application needs to find a list of vehicles which are available during the journey dates entered by the user.
for example user enters he want to go from place A to B during 13th sept, 2014 to 17th sept, 2014
then database needs to return a list of taxi which are available during this period and must not have any exclude date within this period.
Now i have stored the exclude_dates in comma separated format in table (i could have created a separate table but then it would take much more time for a query to execute)
I was trying to create a mysql function which would be called within the actual search query and would return true if there is some there is some excluded date present within the duration and false if not.
these are the queries that i have written
SELECT id, exclude_dates
FROM `taxi_route`
WHERE status = 1
AND `to_city` = 'Surat'
AND `from_city` = 'Ahmedabad'
AND `trip_type` = 2
AND `available_from_date` <= '2014-09-13'
AND available_to_date >= '2014-09-17'
AND STR_TO_DATE((SELECT `split`(exclude_dates, ',', 1)),'%d-%m-%Y')
NOT BETWEEN STR_TO_DATE('13-09-2014','%d-%m-%Y')
AND STR_TO_DATE('17-09-2014','%d-%m-%Y')
Split is a function i have created in mysql to separate the dates present in comma format
DELIMITER $$
CREATE FUNCTION split( str VARCHAR(500), delchar VARCHAR(2), x INT )
RETURNS VARCHAR(500)
BEGIN
RETURN SUBSTR(SUBSTRING_INDEX(str, delchar, x),
LENGTH(SUBSTRING_INDEX(str, delchar, x-1))+IF(x > 1, 2, 1));
END$$
DELIMITER ;
this works fine as far as i pass 1 in split(exclude_dates, ',', 1) , but if the exclude_dates have more then one date then this will not work
can someone please suggest or guide, how this can be accomplished.
snapshot of database is here http://i.imgur.com/JaI8MSx.png
Your query is most likely going to take more time to execute than defining a separate table for exclusion dates. It's not a good practice using comma separated list inside a column for searching purposes, this is against normalization rules.
You should define your tables separately, (e.g. taxi, taxi_route, taxi_route_exclusion, route_exclusion) and later add necessary indexes to make your searches more efficient.
Example:
taxi
---------
id
country
***
***
***
taxi_route
-------------------
id
taxi_id
available_from_date
available_to_date
from_city
to_city
route_exclusion
---------------
id
taxi_id
exclusion_date
And also add a relation table between taxi_route and route_exclusion tables to represent many-to-many relationship. Later define foreign keys on taxi_route_route_exclusion table to point taxi_route and route_exclusion tables.
taxi_route_route_exclusion
--------------------------
taxi_route_id
route_eclusion_id
Define foreign keys like:
taxi_route.taxi_id -> taxi.id
taxi_route_route_exclusion.taxi_route_id -> taxi_route.id
taxi_route_route_exclusion.route_exclusion_id -> route_exclusion.id
Define indexes like:
taxi: IX1 (status, trip_type)
taxi_route: IX1(to_city, from_city, available_from_date, available_to_date)
Your final query should look like this:
SELECT tr.id, re.exclusion_date
FROM `taxi_route` tr JOIN `taxi_route_route_exclusion` trre
ON tr.id = trre.taxi_route_id
JOIN `route_exclusion` re
ON re.id = trre.route_exclusion_id
JOIN `taxi` t
ON t.id = tr.id
WHERE
t.status = 1
AND t.trip_type = 2
AND tr.to_city = 'Surat'
AND tr.from_city = 'Ahmedabad'
AND tr.available_from_date <= '2014-09-13'
AND tr.available_to_date >= '2014-09-17'
How do i start on an if else statement to restrict?
Fields in database :
No_of_vacancy (shows the number of positions available in the company)
Assigned (shows the number of student assigned to company)
EG
ABC Co
No of vancacy = 2
Assigned student = 2
I have done the necessary statement
UPDATE job_details,
student_details
SET
assigned = assigned + 1
WHERE
student_details.jobscope1 = job_details.jobscope
AND student_details.jobscope1 = 'IT';
The above statement works fine. meaning each time query runs. 1 student will be added under assigned field in database. I want the query to stop after assigned field matches the no of vacancy field to avoid duplication.
My logic is that i have to use if else statement to restrict the amount of assigned students from going over the no of vacancy available which is 2.
how do i start?
And if you simply add, to the where, and (assigned + 1) < job_details.No_of_vacancy ?
A user can input it's preferences to find other users.
Now based on that input, I'd like to get the top 10 best matches to the preferences.
What I thought is:
1) Create a select statement that resolves users preferences
if ($stmt = $mysqli->prepare("SELECT sex FROM ledenvoorkeuren WHERE userid = you"))
$stmt->bind_result($ownsex);
2) Create a select statement that checks all users except for yourself
if ($stmt = $mysqli->prepare("SELECT sex FROM ledenvoorkeuren WHERE userid <> you"))
$stmt->bind_result($othersex);
3) Match select statement 1 with select statement 2
while ($stmt->fetch()) {
$match = 0;
if ($ownsex == $othersex) {
$match = $match + 10;
}
// check next preference
4) Start with a variable with value 0, if preference matches -> variable + 10%
Problem is, I can do this for all members, but how can I then select the top 10???
I think I need to do this in the SQL statement, but I have no idea how...
Ofcourse this is one just one preference and a super simple version of my code, but you'll get the idea. There are like 15 preference settings.
// EDIT //
I would also like to see how much the match rating is on screen!
Well, it was a good question from the start so I upvoted it and then wasted about 1 hour to produce the following :)
Data
I have used a DB named test and table named t for our experiment here.
Below you can find a screenshot showing this table's structure (3 int columns, 1 char(1) column) and complete data
As you can see, everything is rather simple - we have a 4 columns, with id serving as primary key, and a few records (rows).
What we want to achieve
We want to be able to select a limited set of rows from this table based upon some complex criteria, involving comparison of several column's values against needed parameters.
Solution
I've decided to create a function for this. SQL statement follows:
use test;
drop function if exists calcMatch;
delimiter //
create function calcMatch (recordId int, neededQty int, neededSex char(1)) returns int
begin
declare selectedQty int;
declare selectedSex char(1);
declare matchValue int;
set matchValue = 0;
select qty, sex into selectedQty, selectedSex from t where id = recordId;
if selectedQty = neededQty then
set matchValue = matchValue + 10;
end if;
if selectedSex = neededSex then
set matchValue = matchValue + 10;
end if;
return matchValue;
end//
delimiter ;
Minor explanation
Function calculates how well one particular record matches the specified set of parameters, returning an int value as a result. The bigger the value - the better the match.
Function accepts 3 parameters:
recordId - id of the record for which we need to calculate the result(match value)
neededQty - needed quantity. if the record's qty matches it, the result will be increased
neededSex - needed sex value, if the record's sex matches it, the result will be increased
Function selects via id specified record from the table, initializes the resulting match value with 0, then makes a comparison of each required columns against needed value. In case of successful comparison the return value is increased by 10.
Live test
So, hopefully this solves your problem. Feel free to use this for your own project, add needed parameters to function and compare them against needed columns in your table.
Cheers!
Use the limit and offset in query:
SELECT sex FROM ledenvoorkeuren WHERE userid = you limit 10 offset 0
This will give the 10 users data of top most.
You can set a limit in your query like this:
SELECT sex FROM ledenvoorkeuren WHERE userid <> yourid AND sex <> yourpreferredsex limit 0, 10
Where the '0' is the offset, and the '10' your limit
More info here
you may try this
SELECT sex FROM ledenvoorkeuren WHERE userid = you limit 0, 10 order by YOUR_PREFERENCE