IF, Join and concat not working in codeigniter - sql

I have two tables, one of which contains 3000 area codes (so just the first half of the postcode) and the other table containing shops details with a column called postcodes_covered which are all the area codes that a particular shop covers for example:
shop 1 (AB1,AB2,AB3,AB4,AB5...), shop 2 (E15,E13,E14 ...) etc. I need to create a report which contains the 3000 area codes and a column that says "Yes" if an area code from table 2 is contained in table 1 or "No" if that area code is not covered. I have written an SQL query which works fine however, i need to write it in codeigniter. The code i have written for codeigniter doesn't seem to work and i don't know why?
SQL query:
select bodyshops_postcode_allocation.area_code,if(postcodes_covered is null,"No","Yes") as "YeN" from bodyshops_postcode_allocation left join bodyshops on bodyshops.postcodes_covered like concat("%",bodyshops_postcode_allocation.area_code,"%");
Codeigniter:
function postcode_allocation()
{
$this->db->select('bodyshops_postcode_allocation.area_code as area_code')
->select('IF(bodyshops.postcodes_covered is null, "No", "Yes") as match_found')
->join('bodyshops', 'bodyshops.postcodes_covered LIKE CONCAT("%",bodyshops_postcode_allocation.area_code,"%")')
->from('bodyshops_postcode_allocation');
$this->load->dbutil();
$data = $this->dbutil->csv_from_result($this->db->get(''));
$this->output->set_header("Content-type: application/vnd.ms-excel");
$this->output->set_header("Content-disposition: attachment; filename=postcode_allocation.csv; size=".strlen($data));
$this->output->set_output($data);
}

When using SQL function like this in CodeIgniter, you need to tell it not to try to escape the query.
->select('IF(bodyshops.postcodes_covered is null, "No", "Yes") as match_found', FALSE)
The FALSE tells CodeIgniter to leave the string as-as and not try to add backticks to it. It doesn't know how to add them in this case, so it messes up your query.
P.S. your join needs to be:
->join('bodyshops', 'bodyshops.postcodes_covered LIKE CONCAT("%",bodyshops_postcode_allocation.area_code,"%")', 'left')
If you want a LEFT JOIN, you need to tell it so.
P.P.S. $this->db->get('') should really just be $this->db->get(). Don't pass it a blank string.

Related

Microsoft SQL Server generates two select queries and puts data in separate columns

I am looking for a query that separate the data with the condition WHERE in the same output but in separates columns.
Example: I have the table Product_2:
I have two separates queries (to separate the products by Produt_Tag):
SELECT
Product_Mark AS "PIT-10_Product_Mark",
Product_Model AS "PIT-10_Product_Model"
FROM Product_2
WHERE Product_Tag = 'PIT-10';
SELECT
Product_Mark AS "PIT-11_Product_Mark",
Product_Model AS "PIT-11_Product_Model"
FROM Product_2
WHERE Product_Tag = 'PIT-11';
And I get this output:
But I need the output to be like this:
Can someone tell me how I need to modify my query to have the four columns in the same table/ output?
Thank you
I forgot to tell that in the data I Have the “Porduct_Mark” that only appears one time. (in reality the data in “Product_Mark” is the name of the place where the instrument is located and one place can have one or two instruments “Product_Model”. At the end I’m looking for the result show in the image here below. I tried to use LEFT JOIN but that don’t work.
here is the new table "Product_2"
Result that I'm looking for:
Luis Ardila
I am assuming Product_PK is the primary key for the table and the repeated value 1002 shown in the question is a mistake. Considering this assumption, you can get the result set using self join as below.
SELECT pa.Product_Mark AS "PIT-10_Product_Mark", pa.Product_Model AS "PIT-10_Product_Model",
pb.Product_Mark AS "PIT-11_Product_Mark", pb.Product_Model AS "PIT-11_Product_Model"
FROM Product_2 pa
INNER JOIN Product_2 pb
ON pa.Product_Mark = pb.Product_Mark
WHERE pa.product_pk != pb.product_pk
and pa.Product_Tag = 'PIT-10'
and pb.Product_Tag = 'PIT-11';
verified same in https://dbfiddle.uk/NiOO8zc1

Option to leave part of a searchable report/form blank in Microsoft access

I have a query in MS Access that is linked to a searchable report which is linked to a form. Part of the report ask users to include two reasons that will be used as criteria for a query. Currently, the report (screenshot) below does not allow for users to simply enter in 1 reason. Users must enter in 2 reasons, and if the reasons are the same, users must enter in the same reason for both fields. For example, If I only have one reason (conflict of Interest),I would need to enter that reason into both reason boxes shown on the screenshot below. I would like to be able to search for one reason while also being able to leave the other reason box blank. So simply entering in Conflict of interest for one box and have it run the query. The code I have for the query is below.
SELECT C1.ConsultID, C1.Consult_No, C1.Consult_Type, C1.Intake_Date, C1.Adult_Peds, C1.Title, C1.ConsultSummary
FROM ([Intersection Query Pre-Reasons] AS C1 LEFT JOIN tblConsultReasons AS C2 ON C1.ConsultID = C2.ConsultID) LEFT JOIN tblConsultReasons AS C3 ON C2.ConsultID = C3.ConsultID
WHERE (((C2.Reason)=Forms!FrmReasonsCriteria!Reason1) And ((C2.ReasonType)="Discerned")) And (C3.Reason)=Forms!FrmReasonsCriteria!Reason2 And C3.ReasonType="Discerned";
How would you recommend I change the code in order to do this. I believe adding a length condition to the second half of the where clause may work. But am not sure what this would look like.
Screenshot of part of the searchable report that queries on reasons
It will be something like this; I haven't tested it because that requires building forms etc and I don't have the time atm:
SELECT C1.ConsultID, C1.Consult_No, C1.Consult_Type, C1.Intake_Date, C1.Adult_Peds, C1.Title, C1.ConsultSummary
FROM ([Intersection Query Pre-Reasons] AS C1
LEFT JOIN tblConsultReasons AS C2 ON C1.ConsultID = C2.ConsultID)
LEFT JOIN tblConsultReasons AS C3 ON C1.ConsultID = C3.ConsultID
WHERE
NOT (nz(Forms!FrmReasonsCriteria!Reason1,'')='' And
nz(Forms!FrmReasonsCriteria!Reason2,'')=''
)
And (
(nz(C2.Reason=Forms!FrmReasonsCriteria!Reason1,'')=''
And C2.ConsultID is null)
Or
(nz(C2.Reason=Forms!FrmReasonsCriteria!Reason1,'')<>'' And
C2.Reason=Forms!FrmReasonsCriteria!Reason1 And
C2.ReasonType="Discerned")
)
And (
(nz(C3.Reason=Forms!FrmReasonsCriteria!Reason2,'')=''
And C3.ConsultID is null)
Or
(nz(C3.Reason=Forms!FrmReasonsCriteria!Reason2,'')<>'' And
C3.Reason=Forms!FrmReasonsCriteria!Reason2 And
C3.ReasonType="Discerned")
)
It can be simplified a bit if we know the data available, and other controls/checks the search boxes may have.

SQL Update based on secondary table in BQ

I have 2 tables, 1 containing the main body of information, the second contains information on country naming convensions. in the information table, countries are identified by Name, I would like to update this string to contain an ISO alpha 3 value which is contained in the naming convention table. e.g turning "United Kingdom" -> "GBR"
I have wrote the following query to make the update, but it effects 0 rows
UPDATE
`db.catagory.test_votes_ds`
SET
`db.catagory.test_votes_ds`.country = `db.catagory.ISO-Alpha`.Alpha_3_code
FROM
`db.catagory.ISO-Alpha`
WHERE
`LOWER(db.catagory.ISO-Alpha`.Country) = LOWER(`db.catagory.test_votes_ds`.country)
I've done an inner join outside of the update between the 2 to make sure that the values are compatable and it returns the correct value, any ideas as to why it isn't updating?
The join used to validate the result is listed below, along with the result:
SELECT
`db.catagory.test_votes_ds`.country, `db.catagory.ISO-Alpha`.Alpha_3_code
from
`db.catagory.test_votes_ds`
inner join
`db.catagory.ISO-Alpha`
on
LOWER(`db.catagory.test_votes_ds`.country) = LOWER(`db.catagory.ISO-Alpha`.Country)
1,Ireland,IRL
2,Australia,AUS
3,United States,USA
4,United Kingdom,GBR
This is not exactly an answer. But your test may not be sufficient. You need to check where the values do not match. So, to return those:
select tv.*
from `db.catagory.test_votes_ds` tv left join
`db.catagory.ISO-Alpha` a
on LOWER(tv.country) = LOWER(a.Country)
where a.Country IS NULL;
I suspect that you will find countries that do not match. So when you run the update, the matches are getting changed the first time. Then the non-matches are never changed.

Multiple entries in crystal reportviewer after adding a SQL expression field

I am using Visual Studio 2017 and I installed the latest crystal reportviewer (22)
What I want is to click a button and create a report from the customer that is selected in the datagridview and the addresses that are shown in the second datagridview.
I managed to do all that but the problem is that a few fields contain numbers which need to be converted to text. An SQL query I would use to do this would be like:
SELECT c.customer_nr, c.status, s.rename FROM CUSTOMERS c INNER JOIN SETUP s on s.id = c.status WHERE s.afk = 'STA'
In my SETUP database I have the columns ID,AFK and RENAME so if the status would be 1 it would convert to text: "ACTIVE", if status = 2 it would convert to "INACTIVE" for example.
I could do something with a formula field like this:
IF ({c.status} = 1) THEN "ACTIVE" ELSE
IF ({c.status}) = 2 THEN "INACTIVE"
but that is not good because i could add another status or change the name in the database etc.
So then I tried with an SQL expression field and I put something like this:
(
SELECT "SETUP"."RENAME" FROM SETUP
WHERE "SETUP"."AFK" = 'STA' AND "SETUP"."ID" = "CUSTOMERS"."STATUS"
)
There must be something wrong because I get the correct conversion but there is only one address in the database but I get 7 pages all with the same address. There should only be one address like I get when I remove the SQL expression field. Where does it go wrong?
* EDIT *
I found the problem. When I create a new database that contains only unique id's then it works. In my original database I have multiple times the id's 1,2,3,4,5 but with different abbreviations in column AFK. Somehow the query looks for the id value and every time it finds this id no matter the AFK value it generates an entry for the address value.
Maybe in the future I will find out how this exactly works for now I have a workaround.
Create a new table for example CrRepSta and add the following entries:
ID,AFK,RENAME
1,STA,Active
2,STA,Inactive
etc
The new query:
(
SELECT "CrRepSta"."RENAME" FROM CrRepSta
WHERE "CrRepSta"."AFK" = 'STA' AND "CrRepSta"."ID" = "CUSTOMERS"."STATUS"
)
And by the way the statement "CrRepSta"."AFK" = 'STA' is not really needed.

MS Access-Return Record Below Current Record

I am very new to Access, and what I am trying to do seems like it should be very simple, but I can't seem to get it.
I am a structural engineer by trade and am making a database to design buildings.
My Diaphragm Analysis Table includes the fields "Floor_Name", "Story_Number", "Wall_Left", and "Wall_Right". I want to write a new query that looks in another query called "Shear_Wall_incremental_Deflection" and pulls information from it based on input from Diaphragm Analysis. I want to take the value in "Wall_Right" (SW01), find the corresponding value in "Shear_Wall_incremental_Deflection", and report the "Elastic_Deflection" corresponding to the "Story_Below" instead of the "Story_Number" in the Diaphragm Analysis Table. In the case where "Story_Number" = 1, "Story_Below" will be 0 and I want the output to be 0.
Same procedure for "Wall_Left", but I'm just taking it one step at a time.
It seems that I need to use a "DLookup" in the expression builder with TWO criteria, one that Wall_Right = Shear_Wall and one that Story_Number = Story_Below, but when I try this I just get errors.
"Shear_Wall_incremental_Deflection" includes shearwalls for all three stories, i.e. it starts at SW01 and goes through SWW for Story Number 3 and then starts again at SW01 for Story Number 2, and so on until Story Number 1. I only show a part of the query results in the image, but rest assured, there are "Elastic_Deflection" values for story numbers below 3.
Here is my attempt in the Expression Builder:
Right_Defl_in: IIf(IsNull([Diaphragm_Analysis]![Wall_Right]),0,DLookUp("[Elastic_Deflection_in]","[Shear_Wall_incremental_Deflection]","[Shear_Wall_incremental_Deflection]![Story_Below]=" & [Diaphragm_Analysis]![Story_Number]))
I know my join from Diaphragm_Analysis "Wall_Left" and "Wall_Right" must include all records from Diaphragm_Analysis and only those from "Shear_Wall_incremental_Deflection"![Shear_Walls] where the joined fields are equal, but that's about all I know.
Please let me know if I need to include more information or send out the database file.
Thanks for your help.
Diaphragm Analysis (Input Table)
Shear_Wall_incremental_Deflection (Partial Image of Query)
I think what you are missing is that you can and should join to Diaphragm_Analysis twice, first time to get the Story_Below value and second to use it to get the corresponding Elastic_Deflection value.
To handle the special case where Story_Below is zero, I would write a separate query (only requires one join this time) and 'OR together' the two queries using the UNION set operation (note the following SQL is untested):
SELECT swid.Floor_Name,
swid.Story_Number,
swid.Wall_Left,
da2.Elastic_Deflection AS Story_Below_Elastic_Deflection
FROM ( Shear_Wall_incremental_Deflection swid
INNER JOIN Diaphragm_Analysis da1
ON da1.ShearWall = swid.Wall_Left )
INNER JOIN Diaphragm_Analysis da2
ON da2.ShearWall = swid.Wall_Left
AND da2.Story_Number = da1.Story_Below
UNION
SELECT swid.Floor_Name,
swid.Story_Number,
swid.Wall_Left,
0 AS Story_Below_Elastic_Deflection
FROM Shear_Wall_incremental_Deflection swid
INNER JOIN Diaphragm_Analysis da1
ON da1.ShearWall = swid.Wall_Left
WHERE da1.Story_Below = 0;
I've assumed that there is no data where Story_Number is zero.